그 외 ... (정리해야함)/꿀팁
swagger 적용 (springdoc-openapi) (feat. spring-boot 3.x)
깡냉쓰
2024. 10. 2. 17:48
728x90
반응형
swagger를 사용하면 api 문서 관리 및 협업에 유용하다.
- 코드와 문서가 분리되어 있으면, 문서 업데이트가 누락될 가능성이 있다. (최신화 x)
기존 프로젝트에 적용되어있는 springfox swagger를 사용하려 했더니 spring-boot 3.x 버전에서 지원을 하지 않는다고 한다. (springfox는 2018년 6월 기준으로 업데이트가 중단됨)
springdoc는 v2 부터 spring-boot 3.x를 지원하니 해당 lib를 이용하면 되겠다. 워낙 문서가 잘되어 있어서 문서만 보고 적용이 가능하다. 자주 사용될만한 설정만 적어 놓자
https://springdoc.org/#Introduction
하나의 SpringBoot 어플리케이션에서 여러개의 OpenAPI 를 정의할 수 있다.
- 외부에 제공하는 publicAPI 와 test 용 supportAPI를 제공한다고 가정하자
- path로 구분할수도 있지만, packageToscan을 이용할 수도 있다.
class SwaggerConfig {
@Bean
fun publicApiGroup(): GroupedOpenApi {
val info =
Info()
.title("결제 API 제공")
.description("<h2>결제 API를 제공합니다.</h2>")
.contact(Contact().name("사용자").url("www.google.com"))
.version("1.0.0")
return GroupedOpenApi
.builder()
.group("Public API")
.pathsToExclude("/api/support/**")
.addOpenApiCustomizer { openApi -> openApi.info(info) }
.build()
}
@Bean
fun supportApiGroup(): GroupedOpenApi {
val info =
Info()
.title("CardPaymentHub Support API")
.description("<h2>결제에 필요한 테스트 API를 지원합니다.</h2>")
.version("1.0.0")
return GroupedOpenApi
.builder()
.group("Support API")
.pathsToMatch("/api/support/**")
.addOpenApiCustomizer { openApi -> openApi.info(info) }
.build()
}
}
공통적인 ApiResponse를 만들어 Controller에 적용해 놓자
- 하나의 애플리케이션이라면 Response 스펙이 대부분 동일할 것 이다.
- 200, 4xx, 5xx 에러일때 리턴되는 응답 규격을 annotation으로 정의해서 적용해두면 API EndPoint 단위가 아닌 class 단위에 적용이 가능하다. (더 좋은 아이디어나 방법이 있으면 코멘트 부탁드립니다!)
200 응답인 경우 결과값의 객체가 그대로 내려가고, 5xx 인 경우 code/message가 내려가는 스펙을 표현하고 싶다면?
응답 스펙 정의
@Schema(description = "API 오류 응답 모델")
data class ErrorResponse(
@field:Schema(description = "에러 코드", example = "USER_VALIDATION_FAILURE")
val code: ErrorCode, // enum 으로 정의하면 swagger 응답 객체 Schema 에 자동으로 enum들이 노출된다.
@field:Schema(description = "에러 메시지", example = "유저 검증 실패")
val message: String,
)
enum class ErrorCode(
val message: String,
) {
USER_VALIDATION_FAILURE("유저 검증 실패")
...
}
Controller에 적용할 annotation 생성
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@ApiResponses(
ApiResponse(responseCode = "200", description = "정상 응답"),
ApiResponse(
responseCode = "500",
description = "서버 오류",
content = [Content(schema = Schema(implementation = ErrorResponse::class))],
),
)
annotation class SwaggerApiResponses
Controller에 적용
@Tag(name = "결제 API")
@RestController
@RequestMapping("/api/payments")
@SwaggerApiResponses
class PaymentController(
....
}
728x90
반응형