Swagger 2.0 어노테이션 정리

Minjae An·2023년 12월 17일
0

Spring Web

목록 보기
4/9
post-thumbnail

About Swagger

Swagger는 API를 문서화하는 데 사용되는 오픈 소스 프레임워크로, API 문서화를 자동화하여 개발 생산성을 향상시킬 수 있다. API를 엑셀, 가이드 문서 등을 통해 관리하는 방법은 주기적인 업데이트가 필요하기 때문에 관리가 쉽지 않고 별도의 시간이 소요된다. 따라서 Swagger를 사용하여 간편하게 API 문서를 관리하며 API를 테스트할 수 있다.

본 글은 Spring Boot 2.x 버전에서 작성되었다.

Swagger 설정

먼저 사용을 위해 의존성을 추가한다.

유의 : Spring Boot 3.x + Swagger

Spring Boot 3.x 버전부터 Swagger의 패키지 경로가 달라져 어느 버전에 매칭해주어야 하는 지 의견이 분분하다. 해당 이슈에 대한 해결책을 기록한 좋은 글이 있어 첨부한다.

build.gradle

dependenciees {
	// ...
	implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
	implementation 'io.springfox:springfox-swagger2:2.9.2'
	implementation 'io.springfox:springfox-swagger-ui:2.9.2'
	// ...
}

그 후 환경설정을 위해 다음과 같은 SwaggerConfig 클래스를 생성해준다.

@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI studyAPI() {
        Info info = new Info()
                .title("Server WorkBook API")
                .description("Server WorkBook API 명세서")
                .version("1.0.0");

        String jwtSchemeName = "JWT TOKEN";
        // API 요청헤더에 인증정보 포함
        SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName);
        // SecuritySchemes 등록
        Components components = new Components()
                .addSecuritySchemes(jwtSchemeName, new SecurityScheme()
                        .name(jwtSchemeName)
                        .type(Type.HTTP)
                        .scheme("bearer")
                        .bearerFormat("JWT"));

        return new OpenAPI()
                .addServersItem(new Server().url("/"))
                .info(info)
                .addSecurityItem(securityRequirement)
                .components(components);
    }
}

Spring Boot에서 Swagger를 사용할 때 설정에는 DocketOpenAPI 라는 두 가지 클래스가 사용되는데 OpenAPI 는 Swagger 3.0 버전부터 도입된 새로운 스펙이다.

일반적으로 Swagger 2.x 버전에서는 Docket 을 사용하고, Swagger 3.0 이상에서는 OpenAPI
사용하는 것이 권장된다. 두 방법 모두 API 문서를 생성하고 설정하는 데 사용된다.

글에 사용된 예제 코드는 이미 편의상 작성된 것을 그냥 사용하여 2.x 버전임에도 OpenAPI 를 이용하였다. 이 점에 유의하자.

이제 /swagger-ui.html 경로를 통하여 Swagger API 문서 페이지를 확인할 수 있다.

Annotations

Swagger에서 API 문서를 위해 사용되는 어노테이션들을 정리해보자.

@ApiOperation - 메서드 설명

@ApiOperation 으로 해당 Controller 의 method 설명을 추가할 수 있다.

@ApiOperation(
	value = "사용자 정보 조회",
	notes = "사용자의 ID를 통해 사용자 정보를 조회한다.")
@GetMapping("/user/{id}")
public UserDTO getUser(@PathVariable(name = "id") String id) {
	User user = userService.findById(id);
	return UserConverter.toUserDTO(user);
}

@ApiImplicitParam - Request Parameter 설명

이 어노테이션을 사용해 해당 API 호출에 필요한 Parameter들의 설명을 기록할 수 있다.

@ApiOperation(
	value = "사용자 정보 조회",
	notes = "사용자의 ID를 통해 사용자 정보를 조회한다.")
@ApiImplicitParam(
	name = "id",
	value = "사용자 아이디",
	required = true,
	dataType = "string",
	paramType = "path",
	defaultValue = "None")
@GetMapping("/user/{id}")
public UserDTO getUser(@PathVariable(name = "id") String id) {
	User user = userService.findById(id);
	return UserConverter.toUserDTO(user);
}

dataType, paramType. required 의 경우 해당 name 을 바탕으로 정보가 자동으로 채워져 생략 가능하다. 만약 해당 메서드의 Parameter가 복수일 경우 @ApiImplicitParams 를 이용하여 복수 개의 @ApiImplicitParam 을 작성할 수 있다.

@ApiOperation(
        value = "자격증 정보 조회"
        , notes = "자격증의 ID를 통해 자격증의 정보를 조회한다.")
    @ApiImplicitParams(
        {
            @ApiImplicitParam(
                name = "id"
                , value = "자격증 아이디"
                , required = true
                , dataType = "string"
                , paramType = "path"
                , defaultValue = "None"
            )
        ,
            @ApiImplicitParam(
                name = "fields"
                , value = "응답 필드 종류"
                , required = false
                , dataType = "string"
                , paramType = "query"
                , defaultValue = ""
            )
        })
    @GetMapping("/licenses/{id}")
    public UserDTO getLicense(@PathVariable(name = "id") String id, @RequestParam(name = "fields", required = false) String fields) {
        return userService.findUserInfoById(id);
    }

@ApiResponse = Response 설명

이 어노테이션을 사용해 해당 메서드의 응답에 대한 설명을 작성할 수 있다.

@ApiResponse(code = 200, message = "성공입니다.")
@GetMapping("/example")
public String test(){
	return "test";
}

복수 개의 응답에 대한 설명은 @ApiResponses 를 이용할 수 있다.

@ApiResponses({
	@ApiResponse(code = 200, message = "성공입니다")
	@ApiResponse(code = 400, message = "올바르지 않은 접근입니다")
})
@GetMapping("/example")
public String test(){
	return "test";
}

Default Response Message 삭제

위 사진에서의 기본 응답 메시지를 삭제하고 싶다면 SwaggerConfig 설정 시 아래 예제 코드와 같이 구성해주면 된다. @ApiResponse 로 설정하지 않은 응답들이 사라진다.

Docket

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
            .useDefaultResponseMessages(false)  // 이 부분을 설정
            .select()
            .apis(RequestHandlerSelectors.basePackage("your.base.package"))
            .paths(PathSelectors.any())
            .build();
    }
}

OpenAPI

@Configuration
public class OpenApiConfig {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .info(new Info().title("Your API").version("1.0"))
            .externalDocs(new ExternalDocumentation()
                .description("Additional documentation")
                .url("https://example.com"))
            .defaultResponseMessages(Collections.emptyList());  // 기본 응답 메시지 비활성화
    }
}

@ApiParam - DTO field 설명

DTO의 필드에 대한 설명을 추가할 수 있다.

@ApiResponses({
	@ApiResponse(code = 200, message = "성공입니다")
	@ApiResponse(code = 400, message = "올바르지 않은 접근입니다")
})
@GetMapping("/example")
public String test(TestDTO testDTO){
	return "test";
}

TestDTO

@Getter
@AllArgsConstructor
public class TestDTO {
	@ApiParam(value = "사용자 ID", required = true)
	private String id;

	@ApiParam(value = "사용자 이름")
	private String name;

	@ApiParam(value = "token 갱신 값")
	private String refreshToken;
}

Controller에서 Parameter에 적용할 수도 있으나 권장되지 않는다.

@ApiModelProperty - DTO 예제 설명

이 어노테이션을 DTO 필드에 추가하면 해당 필드의 예제 데이터를 고지할 수 있다.

@Getter
@AllArgsConstructor
public class TestDTO {
	@ApiModelProperty(
		name = "id",
		example = "mj1111"
	)
	@ApiParam(value = "사용자 ID", required = true)
	private String id;

	@ApiModelProperty(
		example = "김아무개"
	)
	@ApiParam(value = "사용자 이름")
	private String name;

	@ApiParam(value = "token 갱신 값")
	private String refreshToken;
}

name 은 생략이 가능하다.

@ApiIgnore - Swagger UI 기록 x

@ApiResponses({
    @ApiResponse(code = 200, message = "성공입니다.")
    , @ApiResponse(code = 400, message = "접근이 올바르지 않습니다.")
})
@ApiImplicitParam(
    name = "id"
    , value = "사용자 아이디"
    , required = true
    , dataType = "string"
    , paramType = "path"
    , defaultValue = "None")
@GetMapping("/notices/{id}")
public String test(UserDTO userDTO) {
    return "test";
}

위 코드에서는 id 만 표기하면 되는데, Parameter가 DTO의 형태이기 때문에 관련한 모든 Parameter가 노출되게 된다. @ApiIgnore 를 추가하면 @ApiImplicitParam 으로 선언하지 않은 Parameter 정보들을 UI 상에 표현되지 않게 할 수 있다.

@ApiResponses({
    @ApiResponse(code = 200, message = "성공입니다.")
    , @ApiResponse(code = 400, message = "접근이 올바르지 않습니다.")
})
@ApiImplicitParam(
    name = "id"
    , value = "사용자 아이디"
    , required = true
    , dataType = "string"
    , paramType = "path"
    , defaultValue = "None")
@GetMapping("/notices/{id}")
public String test(@ApiIgnore UserDTO userDTO) {
    return "test";
}

한편, 메서드의 return type 앞에 명시하여 해당 메서드를 아예 UI 상에 노출되지 않게 구성할 수도 있다.

@ApiResponses({
    @ApiResponse(code = 200, message = "성공입니다.")
    , @ApiResponse(code = 400, message = "접근이 올바르지 않습니다.")
})
@ApiImplicitParam(
    name = "id"
    , value = "사용자 아이디"
    , required = true
    , dataType = "string"
    , paramType = "path"
    , defaultValue = "None")
@GetMapping("/notices/{id}")
public @ApiIgnore String test(UserDTO userDTO) {
    return "test";
}

Swagger UI API 화면 커스텀

SwaggerConfig 에서 2.0 버전의 경우 DocketapiInfo(ApiInfo Type) , 3.0 버전의 경우 OpenAPIinfo(Info info) 를 작성하여 Swagger UI 기본 화면의 API 설명 문구 등을 커스텀할 수 있다.

참고

profile
내가 쓴 코드가 남의 고통이 되지 않도록 하자

0개의 댓글