πŸš€ Spring Boot 3 + Swagger(OpenAPI 3) 적용 κ°€μ΄λ“œ

Dev96Β·2025λ…„ 9μ›” 11일
post-thumbnail

πŸ“ κ°œμš”

λ°±μ—”λ“œ APIλ₯Ό κ°œλ°œν•˜λ‹€ 보면 ν”„λ‘ νŠΈμ—”λ“œ/QA νŒ€κ³Ό API λͺ…μ„Έλ₯Ό λ¬Έμ„œλ‘œ κ³΅μœ ν•˜λŠ” 일이 ν•„μˆ˜μ μž…λ‹ˆλ‹€.
κ³Όκ±°μ—λŠ” Excelμ΄λ‚˜ Wiki에 μˆ˜λ™μœΌλ‘œ μž‘μ„±ν–ˆμ§€λ§Œ, μ΄μ œλŠ” Swagger(OpenAPI) λ₯Ό 톡해 API λ¬Έμ„œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜κ³  μœ μ§€λ³΄μˆ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이번 κΈ€μ—μ„œλŠ” Spring Boot 3.4 + Java 21 + Gradle ν™˜κ²½μ„ κΈ°μ€€μœΌλ‘œ, Swaggerλ₯Ό μ μš©ν•˜κ³  μš΄μ˜ν•  λ•Œμ˜ Best Practiceλ₯Ό μ†Œκ°œν•©λ‹ˆλ‹€.


πŸ”§ 1. μ˜μ‘΄μ„± μΆ”κ°€

build.gradle에 OpenAPI κ΄€λ ¨ μ˜μ‘΄μ„±μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
Spring Boot 3μ—μ„œλŠ” springdoc-openapi λΌμ΄λΈŒλŸ¬λ¦¬κ°€ κ°€μž₯ 많이 μ‚¬μš©λ©λ‹ˆλ‹€.

dependencies {
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'
}

πŸ“Œ 2. Swagger UI μ ‘κ·Ό 방법

μ˜μ‘΄μ„±λ§Œ μΆ”κ°€ν•˜λ©΄ μžλ™μœΌλ‘œ Swagger UI κ°€ ν™œμ„±ν™”λ©λ‹ˆλ‹€.

기본 경둜: http://{{호슀트}}:{{포트}}/swagger-ui.html

OpenAPI λ¬Έμ„œ(JSON): http://{{호슀트}}:{{포트}}/v1/api-docs

νšŒμ‚¬ λ‚΄ λ³΄μ•ˆ 정책에 따라 μ ‘κ·Ό κΆŒν•œμ„ μ œμ–΄ν•˜κ±°λ‚˜, ν”„λ‘œν•„λ³„λ‘œ 섀정을 λΆ„λ¦¬ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.


βš™οΈ 3. Swagger μ„€μ • μ»€μŠ€ν„°λ§ˆμ΄μ§•

/**
 * Swagger UI 상단에 ν‘œμ‹œλ˜λŠ” API 정보가 이 λΆ€λΆ„μ—μ„œ μ„€μ •
 */
@Configuration
@OpenAPIDefinition(
        info = @Info(
                title = "ν…ŒμŠ€νŠΈ μ „μš© API",
                description = "개인적으둜 ν…ŒμŠ€νŠΈν•˜κΈ° μœ„ν•œ API λ¬Έμ„œμž…λ‹ˆλ‹€",
                version = "v1"
        )
)
public class SwaggerConfiguration {

}



/**
 * Swagger ν™”λ©΄μ—μ„œ μ‚¬μš©μž νŽΈμ˜μ„±μ„ λ†’μ΄λŠ” μ˜΅μ…˜
 * Swagger UIμ—μ„œ μ‚¬μš©μž/κ΄€λ¦¬μž APIλ₯Ό νƒ­μœΌλ‘œ ꡬ뢄
 */

springdoc:
  default-consumes-media-type: application/json
  default-produces-media-type: application/json
  api-docs:
    path: /v1/api-docs
  swagger-ui:
    path: /swagger-ui.html
    operations-sorter: alpha
    tags-sorter: alpha
    display-query-params-without-oauth2: true
    disable-swagger-default-url: true
    doc-expansion: list
    defaultModelsExpandDepth: 1
    defaultModelExpandDepth: 2
    defaultModelRendering: model
    show-extensions: true
    show-common-extensions: true
    display-request-duration: true
    try-it-out-enabled: true
  group-configs:
    - group: μ‚¬μš©μž
      paths-to-match:
        - /v1/member/**
        - /v1/board/**
    - group: κ΄€λ¦¬μž
      paths-to-match:
        - /v1/admin/**

πŸ›  4. Controller 예제

/**
 * μ‚¬μš©μž 생성 API
 */
    @Operation(
            summary = "μ‚¬μš©μž 생성",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    required = true,
                    content = @Content(
                            mediaType = "application/json",
                            schema = @Schema(implementation = CreateMemberRequest.class)
                    )
            ),
            responses = {
                    @ApiResponse(
                            responseCode = "201",
                            description = "μ‚¬μš©μž 생성 μ™„λ£Œ",
                            content = {
                                    @Content(
                                            mediaType = "application/json",
                                            schema = @Schema(implementation = CommonResponse.class)
                                    ),
                            }
                    ),
            }
    )
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public CommonResponse createMember(@Valid @RequestBody CreateMemberRequest createMemberRequest) {
        Member member = memberWebMapper.toDomain(createMemberRequest);
        Member resultMember = createMemberUseCase.createMember(member);
        CreateMemberResponse createMemberResponse = memberWebMapper.toCreateMemberResponse(resultMember);
        CommonResponse commonResponse = new CommonResponse<>("μ‚¬μš©μž 생성이 μ •μƒμ μœΌλ‘œ μ²˜λ¦¬λμŠ΅λ‹ˆλ‹€", createMemberResponse);
        return commonResponse;
    }

πŸ‘‰ 5. ν™œμš© 사둀

  • λ°±μ—”λ“œ(Spring Boot) β†’ /v1/api-docs 제곡
  • ν”„λ‘ νŠΈμ—”λ“œ β†’ OpenAPI Generator, orval, swagger-typescript-api 등을 ν™œμš©ν•˜μ—¬
    • νƒ€μž… μ •μ˜
    • API 호좜 μ½”λ“œ
    • React Query/SWR ν›… μžλ™μœΌλ‘œ 생성 κ°€λŠ₯

🎯 6. 마무리

Swagger(OpenAPI)λŠ” API 개발/μš΄μ˜μ—μ„œ ν˜‘μ—… νš¨μœ¨μ„ κ·ΉλŒ€ν™”ν•˜λŠ” λ„κ΅¬μž…λ‹ˆλ‹€.
Spring Bootμ—μ„œλŠ” springdoc-openapiλ₯Ό 톡해 μ‰½κ²Œ μ μš©ν•  수 있고,
λ³΄μ•ˆ/ν”„λ‘œν•„ 뢄리/λ¬Έμ„œ κ΄€λ¦¬κΉŒμ§€ μ‹ κ²½μ“΄λ‹€λ©΄ 싀무에 λ°”λ‘œ 적용 κ°€λŠ₯ν•œ 베슀트 ν”„λž™ν‹°μŠ€κ°€ λ©λ‹ˆλ‹€.

profile
λ‹€μ–‘ν•œ κ²½ν—˜κ³Ό μ‹€λ¬΄μ˜ 깊이둜 평가받고 싢은 μ‚¬λžŒλ“€μ„ μœ„ν•΄ κΈ°λ‘ν•©λ‹ˆλ‹€. μ‹€λ¬΄μ—μ„œ λΆ€λ”ͺ히며 배운 것듀이 κ°€μž₯ 였래 λ‚¨λŠ”λ‹€κ³  λ―ΏμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€