Spring Boot 3에 Swagger 적용하기(springdoc-openapi)

이민재·2024년 3월 5일
0
implementation 'io.springfox:springfox-swagger2:3.0.0'

이전에 Swagger를 적용하여 api를 문서화를 진행한 적이 있어서 이번에도 똑같이 Swagger를 통한 문서화를 진행하려고 했다.

spring boot 3.2.3을 사용하고 springfox3.0.0을 추가했다. 하지만 오류가 발생하여 SpringFox를 사용할 수 없었다.

spring boot 3버전에서는 SpringFox 가 적용되지 않는다. Java EE가 Spring boot 3에서는 JakartaEE로 변경되었지만 현재 JakartaEE를 지원하는 SpringFox는 없기 때문이다.

spring boot의 버전을 낮추거나, springdoc-openapi를 이용해야 한다.

[Spring Fox]
2020년 7월 3.0.0 버전을 마지막으로 업데이트 되고 있지 않음

[Spring Doc]
2023년 4월 1.7.0 버전 업데이트

dependency 설정

// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
//	implementation 'org.springdoc:springdoc-openapi-ui:1.7.0'  해당 의존성은 오류 발생
	implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'

OpenAPI Bean 등록

@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .components(new Components())
                .info(apiInfo());
    }

    private Info apiInfo() {
        return new Info()
                .title("Springdoc 테스트")
                .description("Springdoc을 사용한 Swagger UI 테스트")
                .version("1.0.0");
    }
}

application.yml 설정

springfox에서는 bean으로 설정을 등록했었지만 springdoc는 apllication에서 모든 설정을 등록 할 수 있다.

springdoc:
  packagesToScan: com.nklcb.cosmos
  default-consumes-media-type: application/json;charset=UTF-8
  default-produces-media-type: application/json;charset=UTF-8
  swagger-ui:
    path: /swagger.html
    disable-swagger-default-url: true
    display-request-duration: true
    operations-sorter: alpha

모든 설정이 완료 된 후 path에 설정해둔 경로로 이동하면 정상적으로 화면이 보인다.

spring security 설정

향후 추가

API 스펙 작성

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/members")
@Validated
@Tag(name = "Member", description = "Member API")
public class MemberController {

	@GetMapping("/{memberId}")
	@Operation(summary = "Get member profile", description = "특정 멤버의 상세 정보를 조회한다.")
	@ApiResponses(value = {
    	@ApiResponse(responseCode = "200", description = "성공",
        content = {@Content(schema = @Schema(implementation = MemberProfileRes.class))}),
    	@ApiResponse(responseCode = "404", description = "해당 ID의 유저가 존재하지 않습니다."),
		})
    public MemberProfileRes getMemberProfile(
        @PathVariable
        @Positive(message = "유저 ID는 양수입니다.")
        @Schema(description = "Member ID", example = "1")
        Long memberId,

        // TODO: Replace with member ID from JWT or that from any other authentication method
        @Parameter(name = "loginId", description = "로그인 유저 ID 값", example = "3", required = true)
        @Positive(message = "유저 ID는 양수입니다.") @RequestParam final Long loginId,

        @RequestBody @Valid MemberProfileUpdateReq request
    ) {
      return memberMapper.toResponse(
          memberService.findProfileByMemberId(memberId, loginId)
      );
  	}
 
}
@Tag(name = "Member", description = "Member API")

@Tag를 통해 controller 단위에 tag를 지정해 준다.

Swaaget UI에서는 tag단위로 그룹핑 된다.

@Operation(summary = "Get member profile", description = "특정 멤버의 상세 정보를 조회한다.")

@Operation을 이용해 해당 API가 어떤 리소스를 나타내는지 간략한 설명을 추가할 수 있다.

@ApiResponses(value = {
    	@ApiResponse(responseCode = "200", description = "성공",
        content = {@Content(schema = @Schema(implementation = MemberProfileRes.class))}),
    	@ApiResponse(responseCode = "404", description = "해당 ID의 유저가 존재하지 않습니다."),
		})

@ApiResponses를 이용해 해당 API의 Response 정보들을 나타낼 수 있다.

@ApiResponse는 단일 Response에 대한 정보를 나타낸다.

responseCode : HTTP status code
description : 이 response의 의미
content : response 데이터 포맷. void이거나 response field에 대한 설명을 추가하지 않을거라면 생략하면 된다.

@ApiResponses(value = {
	@ApiResponse(responseCode = "200", description = "성공",
		content = {
			@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = MemberRes.class)))
		})
})

응답이 list 일 경우 arry 옵션 사용


DTO API 스펙 작성

@Getter
@AllArgsConstructor
@Schema(description = "Member profile update request")
public class MemberProfileUpdateReq {
 
  @NotBlank(message = "사용자 이름을 입력해주세요.")
  @Length(max = 20, message = "사용자 이름은 20글자 이하로 입력해야 합니다.")
  @Schema(description = "member name", example = "John Doe")
  private String name;
 
  @NotBlank(message = "사용자 닉네임을 입력해주세요.")
  @Length(max = 20, message = "사용자 닉네임은 20글자 이하로 입력해야 합니다.")
  @Schema(description = "member nickname", example = "johndoe")
  private String nickname;
 
  @NotBlank
  @Schema(description = "member profile emoji", example = "👨🏻‍💻")
  private String profileEmoji;
}

@Schema를 사용해서 클래스 설명 및 변수 설명을 설정할수 있다.

변수가 특정 객체를 타입으로 가진다면 implementation 옵션을 사용한다.

@NotBlank, @Length 등 Spring validation은 자동으로 인식할 수 있다.


이전 프로젝트에서 swagger를 적용할 때 api를 개발하면서 swagger 사용법을 검색하고 적용하다 보니 필요한 내용이 누락되었던 경우가 조금씩 발생했었다. 덕분에 다른 팀원들이 api관련해서 swagger가 있어도 설명해주라는 경우가 있었는데 이번에는 본격적인 프로젝트 시작 전에 사용법을 정리하고 이런 경우가 없도록 깔끔하게 정리하고 싶다.

profile
초보 개발자

0개의 댓글