catsridingCATSRIDING|OCEANWAVES
Dev

Springdoc 적용하기

jynn@catsriding.com
Nov 13, 2023
Published byJynn
999
Springdoc 적용하기

Documenting REST APIs with SpringDoc

스웨거(Swagger)는 API 문서를 자동화하고 실제 테스트 요청을 보낼 수 있는 HTTP 클라이언트 환경을 제공합니다. Spring REST Docs는 테스트 코드를 작성하고, 이 코드를 통해 생성된 스니펫을 사용하여 문서를 작성해야 하는 반면, 스웨거는 어노테이션 기반으로 많은 부분을 자동화합니다. 또한, 스웨거 문서를 통해 API 요청을 전송할 수 있어 협업 시 매우 유용합니다.

하지만, 운영 코드와 완전히 분리된 환경에서 문서화가 가능한 Spring REST Docs와 비교할 때, 스웨거는 운영 코드에 침투적이기 때문에, 이로 인해 상세하고 가독성이 뛰어난 문서를 작성하는 데 한계가 있을 수 있습니다.

이러한 이유로, 스웨거를 단순히 API 테스트 도구로 사용하고, API의 상세 스펙을 담은 문서는 Spring REST Docs를 통해 작성하는 접근 방식도 사용됩니다.

이번 포스팅에서는 스웨거를 Spring Framework에 최적화한 SpringDoc 라이브러리를 적용하여 REST API 문서를 작성하는 방법에 대해 살펴보겠습니다.

Prerequisites

스웨거 문서화를 진행하기 위해 Spring Boot 프로젝트를 생성하고 CRUD에 대응하는 REST API를 추가합니다.

먼저, 읽기(Read) 작업을 처리하는 ReadController를 작성합니다. 이 컨트롤러는 사용자 정보를 조회하는 두 가지 API를 제공합니다.

SpringDocReadController.java
private final SpringDocReadService readService;  

@GetMapping("/{id}")  
public ResponseEntity<?> userDetailsApi(
        @PathVariable Long id) {  
    UserResponse user = readService.read(id);  
    return ResponseEntity  
            .ok(user);  
}  

@GetMapping  
public ResponseEntity<?> usersApi() {  
    List<UserResponse> users = readService.read();  
    return ResponseEntity  
            .ok(users);  
}  

다음으로, 쓰기(Write) 작업을 처리하는 WriteController를 작성합니다. 이 컨트롤러는 사용자 생성, 업데이트, 삭제, 프로필 이미지 업로드를 위한 API를 제공합니다.

SpringDocWriteController.java
private final SpringDocWriteService writeService;  

@PostMapping  
public ResponseEntity<?> userCreateApi(
        @Valid @RequestBody UserCreateRequest request) {  
    writeService.write(request);  
    return ResponseEntity  
            .ok(RestApiResponse.success());  
}  

@PutMapping("/{id}")  
public ResponseEntity<?> userUpdateApi(
        @PathVariable Long id,  
        @Valid @RequestBody UserUpdateRequest request) {  
    writeService.update(id, request);  
    return ResponseEntity  
            .ok(RestApiResponse.success());  
}  

@PostMapping("/avatar")  
public ResponseEntity<?> userAvatarApi(
        @RequestPart(value = "avatar") MultipartFile avatar) {  
    writeService.update(avatar);  
    return ResponseEntity  
            .ok(RestApiResponse.success());  
}  

@DeleteMapping("/{id}")  
public ResponseEntity<?> userRemoveApi(
        @PathVariable Long id) {  
    writeService.remove(id);  
    return ResponseEntity  
            .ok(RestApiResponse.success());  
}
  • Java 17
  • Spring Boot 3.2.0
  • Gradle 8
  • Lombok

Configuring SpringDoc

build.gradle에 Spring Boot 버전에 호환되는 SpringDoc 라이브러리 의존성을 추가합니다. 공식 문서에서 호환되는 버전에 대한 정보를 확인할 수 있으며, 버전에 따른 사용법은 크게 다르지 않았습니다.

  • Spring Boot v3.x: SpringDoc v2.x
  • Spring Boot v2.x: SpringDoc v1.x
build.gradle
dependencies {   
    // SpringDoc  
+   implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
}

SpringDoc은 의존성만 추가하면 바로 사용할 수 있습니다. 커스터마이징이 필요한 경우에는 Swagger OpenAPI 스펙에 대응하는 OpenAPI 클래스를 직접 구현합니다.

SpringDocConfig
@Configuration  
@RequiredArgsConstructor  
public class SpringDocConfig {  

    @Bean  
    public OpenAPI openApi() {  
        return new OpenAPI()  
                .info(apiInfo())  
                .servers(servers())
    }  
  
    private Info apiInfo() {  
        return new Info()  
                .title("CATSRIDING | 🌊 OCEANWAVES")  
                .description("Swagger v3 SpringDoc 적용하기")  
                .termsOfService("https://www.catsriding.dev/terms")  
                .contact(new Contact().name("Jynn").email("catsriding@gmail.com"))  
                .license(new License().name("© 2020-present Jynn. All Rights reserved."))  
                .version("v1.0.0");  
    }  
  
    private static List<Server> servers() {  
        Server localServer = new Server();  
        localServer.setUrl("http://localhost:8080");  
        localServer.setDescription(" Local Server");  
  
        Server devServer = new Server();  
        devServer.setUrl("https://catsriding.dev");  
        devServer.setDescription("🛸 Dev Server");  
  
        return List.of(localServer, devServer);  
    }  
}

SpringDoc에서 커스터마이징이 가능한 설정은 매우 다양하며, 이를 통해 API 문서를 더욱 세밀하게 조정할 수 있습니다. 다음은 SpringDoc의 주요 커스터마이징 옵션들입니다:

  • info(): 문서에 대한 일반적인 정보를 설정합니다.
    • title(): 문서 제목
    • description(): 문서 설명
    • termsOfService(): 서비스 이용 약관 URL
    • contact(): 작성자 연락처
    • license(): 라이센스 정보
    • version(): API 문서 버전
  • servers(): API가 배포되는 서버들에 대한 정보를 설정합니다.
    • url(): 서버 URL
    • description(): 서버 설명
  • tags(): API 엔드포인트를 그룹화하는 태그를 정의합니다.
    • name(): 태그의 이름
    • description(): 태그에 대한 설명
  • externalDocs(): API 문서와 관련된 추가 문서의 링크를 제공합니다.
    • description(): 추가 문서에 대한 설명
    • url(): 추가 문서의 URL
  • components(): API에서 사용할 공통 스키마, 파라미터, 응답, 보안 스키마 등을 정의합니다.
    • schemas: 공통 스키마 정의
    • parameters: 공통 파라미터 정의
    • responses: 공통 응답 정의
    • securitySchemes: 보안 스키마 정의
  • security(): API의 보안 요구 사항을 정의합니다.
    • name(): 보안 스키마의 이름
    • scopes(): 보안 스키마에 필요한 스코프
  • paths(): API의 각 경로와 해당 경로에 대한 작업(Operation)을 정의합니다.
    • get(), post(), put(), delete() 등의 메서드에 대한 설정

SpringDoc은 스웨거 UI 및 HTTP 클라이언트 환경에 대한 다양한 속성을 제공하여 기본 설정을 편리하게 변경할 수 있도록 합니다. 이러한 설정은 SpringDoc 공식 문서에서 확인할 수 있으며, 이를 통해 다양한 커스터마이징 옵션을 활용하여 API 문서를 더욱 세밀하고 구체적으로 조정할 수 있습니다.

application.properties
springdoc.swagger-ui.path= # Swagger UI HTML 문서의 경로를 설정합니다.
springdoc.swagger-ui.groups-order= # API 그룹을 오름차순으로 정렬합니다.
springdoc.swagger-ui.operationsSorter= # 메서드 기준으로 작업(Operation)을 정렬합니다.
springdoc.swagger-ui.disable-swagger-default-url= # 기본 Swagger URL 비활성화합니다.
springdoc.swagger-ui.display-request-duration= # 요청 지속 시간 표시를 활성화합니다.
springdoc.swagger-ui.configUrl= # 외부 설정 문서의 URL을 설정합니다.
springdoc.swagger-ui.layout= # 상위 레이아웃 컴포넌트를 설정합니다.
springdoc.swagger-ui.validatorUrl= # 유효성 검사기의 URL을 설정합니다.
springdoc.swagger-ui.tryItOutEnabled= # "Try it out" 기능을 기본적으로 활성화합니다.
springdoc.swagger-ui.filter= # 필터링 기능을 활성화합니다.
springdoc.swagger-ui.tagsSorter= # 태그 목록을 알파벳 순으로 정렬합니다.
springdoc.swagger-ui.oauth2RedirectUrl= # OAuth 리디렉션 URL을 설정합니다.
springdoc.swagger-ui.displayOperationId= # operationId를 표시합니다.
springdoc.swagger-ui.deepLinking= # 딥 링크 기능을 활성화합니다.
springdoc.swagger-ui.defaultModelsExpandDepth= # 모델 확장 깊이를 설정합니다.
springdoc.swagger-ui.defaultModelExpandDepth= # 모델 예시 섹션의 확장 깊이를 설정합니다.
springdoc.swagger-ui.defaultModelRendering= # 기본 모델 렌더링 설정을 설정합니다.
springdoc.swagger-ui.docExpansion= # 작업과 태그의 기본 확장 설정을 설정합니다.
springdoc.swagger-ui.maxDisplayedTags= # 표시할 최대 태그 수를 설정합니다.
springdoc.swagger-ui.showExtensions= # 확장 필드와 값을 표시합니다.
springdoc.swagger-ui.url= # 사용자 정의 OpenAPI 파일의 경로를 설정합니다.
springdoc.swagger-ui.showCommonExtensions= # 일반 확장 필드를 표시합니다.
springdoc.swagger-ui.supportedSubmitMethods= # "Try it out" 기능을 사용할 수 있는 HTTP 메서드를 설정합니다.
springdoc.swagger-ui.queryConfigEnabled= # URL 검색 매개변수를 통한 설정 재정의를 비활성화합니다.
springdoc.swagger-ui.oauth.additionalQueryStringParams= # 추가 쿼리 매개변수를 설정합니다.
springdoc.api-docs.path= # OpenAPI 문서의 경로를 설정합니다.
springdoc.api-docs.enabled= # OpenAPI 문서 생성을 활성화합니다.
springdoc.api-docs.version= # OpenAPI 버전을 설정합니다 (예: OpenAPI 3.1).
springdoc.api-docs.resolve-schema-properties= # @Schema 속성에서 속성 해석을 활성화합니다.
springdoc.api-docs.remove-broken-reference-definitions= # 깨진 참조 정의 제거를 비활성화합니다.
springdoc.api-docs.writer-with-default-pretty-printer= # OpenAPI 사양의 예쁘게 인쇄를 활성화합니다.
springdoc.api-docs.model-converters.deprecating-converter.enabled= # 모델 변환기 사용 중지 설정을 비활성화합니다.
springdoc.api-docs.model-converters.polymorphic-converter.enabled= # 다형성 모델 변환기를 비활성화합니다.
springdoc.api-docs.model-converters.pageable-converter.enabled= # 페이지 모델 변환기를 비활성화합니다.
springdoc.api-docs.model-converters.sort-converter.enabled= # 정렬 변환기를 비활성화합니다.
springdoc.api-docs.use-fqn= # 완전한 정규 이름 사용을 활성화합니다.
springdoc.api-docs.pre-loading-enabled= # 애플리케이션 시작 시 OpenAPI를 미리 로드합니다.
springdoc.api-docs.pre-loading-locales= # OpenAPI를 로드할 로케일 목록을 설정합니다.
springdoc.api-docs.writer-with-order-by-keys= # 결정적/알파벳 순서 정렬을 활성화합니다.
springdoc.api-docs.use-management-port= # 관리 포트에서 Swagger UI를 노출합니다.
springdoc.api-docs.disable-i18n= # 자동 번역을 비활성화합니다.
springdoc.api-docs.show-spring-cloud-functions= # Spring Cloud Function 웹 엔드포인트를 표시합니다.
springdoc.api-docs.enable-groovy= # Groovy 지원을 활성화합니다.
springdoc.api-docs.enable-spring-security= # Spring Security 지원을 활성화합니다.
springdoc.api-docs.enable-kotlin= # Kotlin 지원을 활성화합니다.
springdoc.api-docs.enable-hateoas= # Spring HATEOAS 지원을 활성화합니다.
springdoc.api-docs.enable-data-rest= # Spring Data REST 지원을 활성화합니다.
springdoc.api-docs.default-flat-param-object= # 기본적으로 플랫 매개변수 객체를 사용합니다.
springdoc.api-docs.default-support-form-data= # 양식 데이터를 지원하도록 설정합니다.
springdoc.api-docs.nullable-request-parameter-enabled= # Kotlin에서 nullable 요청 매개변수 지원을 활성화합니다.
springdoc.api-docs.show-oauth2-endpoints= # OAuth2 엔드포인트를 표시합니다.
springdoc.api-docs.resolve-extensions-properties= # @ExtensionProperty 속성 지원을 활성화합니다.
springdoc.api-docs.enable-default-api-docs= # 기본 OpenAPI 엔드포인트를 활성화합니다 (/v3/api-docs).
springdoc.api-docs.trim-kotlin-indent= # Kotlin의 @Operation 주석 해석 시 들여쓰기를 조정합니다.
springdoc.group-configs[].consumes-to-match= # 매칭할 소비 미디어 타입 목록을 설정합니다.
springdoc.group-configs[].headers-to-match= # 매칭할 헤더 목록을 설정합니다.
springdoc.webjars.prefix= # Swagger UI의 WebJars 경로를 설정합니다.

SpringDoc 공식 문서를 참고하여 application.yml에 필요한 모든 속성을 추가합니다.

application.yml
springdoc:  
  swagger-ui:  
    path: /docs # Swagger UI HTML 문서의 경로를 설정합니다.
    groups-order: asc # API 그룹을 오름차순으로 정렬합니다.
    operationsSorter: method # 메서드 기준으로 작업(Operation)을 정렬합니다.
    disable-swagger-default-url: true # 기본 Swagger URL 비활성화합니다.
    display-request-duration: true # 요청 지속 시간 표시를 활성화합니다.
  api-docs:  
    path: /api-docs # OpenAPI 문서의 경로를 설정합니다.
    enabled: true # OpenAPI 문서 생성을 활성화합니다.
    version: openapi_3_1 # OpenAPI 버전을 설정합니다.
  show-actuator: false # Actuator 엔드포인트를 문서에 표시하지 않도록 설정합니다.
  default-consumes-media-type: application/json # 기본 소비 미디어 타입을 설정합니다.
  default-produces-media-type: application/json # 기본 생성 미디어 타입을 설정합니다.
  paths-to-match:  
    - /** # 문서화할 경로 패턴을 설정합니다.

서버를 구동한 후 브라우저로 /swagger-ui/index.html에 접속하여 스웨거 UI 화면이 정상적으로 표시되는지 확인합니다.

documentation-rest-api-with-springdoc_01.png

SpringDoc Annotations

다음은 REST API 문서를 작성할 때 자주 사용하는 SpringDoc 어노테이션 리스트입니다.

  • @Tag: 클래스 또는 메서드를 논리적으로 그룹화하는 데 사용합니다.
    • name: 태그의 이름입니다. 이는 필수 속성입니다.
    • description: 태그에 대한 설명입니다. 이는 선택적 속성이며 기본값은 빈 문자열입니다.
  • @Operation: 자동으로 생성된 문서를 커스터마이징합니다.
    • summary: 메서드가 하는 일에 대한 개요를 추가합니다.
    • description: 메서드가 하는 일에 대해 자세한 설명을 추가합니다.
    • tags: 작업을 논리적으로 그룹화합니다.
    • responses: HTTP 상태 코드별로 매핑된 API 응답에 대한 설명을 작성할 수 있습니다. @Operation 어노테이션에 모든 내용을 추가하는 경우 가독성이 매우 떨어지기 때문에 아래 @ApiResponses로 응답에 대한 스펙을 분리하여 작성하는 것이 좋습니다.
  • @ApiResponse: API 요청에 대한 응답 페이로드를 문서화합니다.
    • responseCode: HTTP 응답 코드입니다.
    • description: 해당 응답에 대한 설명입니다.
    • content: 요청 처리 결과에 대해 예상되는 응답 바디에 대한 정보를 추가합니다.
  • @ApiResponses: @ApiResponse를 그룹화하여 응답 처리 결과에 따른 응답 페이로드를 문서화할 때 유용합니다.
    • value: 하나 이상의 @ApiResponse를 배열 형태로 포함합니다.
  • @Parameter: API 요청 파라미터에 대한 설명을 추가할 때 사용합니다.
    • description: 이 매개변수의 용도를 설명합니다.
    • required: Boolean 값으로, 이 매개변수가 반드시 포함되어야 하는지 여부를 나타냅니다. 기본값은 false입니다.
    • example: 이 매개변수의 예제 값을 제공합니다.
    • hidden: Boolean 값으로, 이 매개변수가 API 문서에서 숨겨져야 하는지를 나타냅니다. 기본값은 false입니다.
  • @Parameters: @Parameter 어노테이션을 그룹화합니다.
    • value: 하나 이상의 @Parameter를 배열 형태로 포함합니다.
  • @Schema: 요청 바디(Request Body) 또는 응답 바디(Response Body)와 같이 API를 통해 클라이언트와 서버 사이에서 교환되는 데이터의 구조를 문서화할 때 유용합니다.
    • description: 필드에 대한 간단한 설명을 추가합니다.
    • example: 해당 필드의 예시 값을 제공합니다. 이는 API 문서를 읽는 사람들에게 이 필드가 어떤 종류의 데이터를 가지는지 대략적으로 보여주는 역할을 합니다.
    • defaultValue: API 요청 시 기본 값을 설정합니다.
    • required: 이 필드가 필수 필드인지 아닌지를 Boolean 값으로 표시합니다.
  • @RequestBody: 요청 바디에 대한 설명을 추가합니다. 이를 통해 클라이언트가 API에 데이터를 전송할 때 기대되는 형식을 문서화할 수 있습니다.
    • description: 요청 바디의 용도를 설명합니다.
    • required: 요청 바디가 필수인지 여부를 나타냅니다. 기본값은 true입니다.
    • content: 요청 바디의 내용 유형과 예제를 설명합니다.
  • @RequestHeader: API 요청 헤더에 대한 설명을 추가합니다.
    • name: 헤더의 이름입니다.
    • description: 헤더의 용도를 설명합니다.
    • required: 헤더가 필수인지 여부를 나타냅니다. 기본값은 false입니다.
    • example: 헤더의 예제 값을 제공합니다.
  • @RequestParam: API 요청 파라미터에 대한 설명을 추가합니다.
    • name: 파라미터의 이름입니다.
    • description: 파라미터의 용도를 설명합니다.
    • required: 파라미터가 필수인지 여부를 나타냅니다. 기본값은 false입니다.
    • example: 파라미터의 예제 값을 제공합니다.
  • @HeaderParam: HTTP 요청 헤더에 대한 설명을 추가합니다.
    • name: 헤더의 이름입니다.
    • description: 헤더의 용도를 설명합니다.
    • required: 헤더가 필수인지 여부를 나타냅니다. 기본값은 false입니다.
    • example: 헤더의 예제 값을 제공합니다.
  • @Content: @ApiResponse@RequestBody 등에서 사용되며, 응답 또는 요청의 미디어 타입과 내용을 정의합니다.
    • mediaType: 콘텐츠 유형을 지정합니다.
    • schema: 콘텐츠의 스키마를 지정합니다.
    • examples: 예제를 제공합니다.
  • @ExampleObject: 예제 객체를 정의합니다.
    • name: 예제의 이름입니다.
    • summary: 예제에 대한 간단한 설명입니다.
    • description: 예제에 대한 상세한 설명입니다.
    • value: 예제의 실제 JSON 값입니다.
    • externalValue: 외부 파일에 위치한 예제 값에 대한 URL입니다.
  • @ArraySchema: 배열 데이터의 스키마를 정의합니다.
    • schema: 배열 요소의 스키마를 지정합니다.
    • minItems: 최소 아이템 수를 지정합니다.
    • maxItems: 최대 아이템 수를 지정합니다.
    • uniqueItems: 아이템의 고유 여부를 지정합니다.
  • @DiscriminatorMapping: 스키마에 대한 차별자 매핑을 정의합니다.
    • value: 차별자의 값입니다.
    • schema: 해당 값에 대한 스키마를 지정합니다.

이 어노테이션들을 활용하면 API의 각 부분을 보다 세밀하고 정확하게 문서화할 수 있습니다. 이를 통해 API 사용자는 API의 작동 방식과 기대되는 입력 및 출력 형식을 쉽게 이해할 수 있습니다.

Documenting REST API

SpringDoc 어노테이션을 활용하여 API 문서화 작업을 진행합니다.

Grouping Controller

현재 조회 요청을 처리하는 컨트롤러와 데이터 변경 요청을 처리하는 컨트롤러를 분리해두었습니다. 스웨거 UI에서도 각각이 별도로 분리되어 있는 것을 확인할 수 있습니다.

  • SpringDocReadController → spring-doc-read-controller
  • SpringDocWriteController → spring-doc-write-controller

하지만 논리적으로는 동일한 그룹으로 볼 수 있기 때문에, 클래스는 다르더라도 스웨거 UI 문서에서는 하나로 통합될 필요가 있습니다. 이를 위해 클래스 레벨에 @Tag 어노테이션을 활용합니다. @Tagname 속성 값이 동일한 경우 하나의 그룹으로 분류됩니다.

먼저, ReadController@Tag 어노테이션을 추가합니다. 이를 통해 조회 요청 관련 API들이 User APIs 그룹으로 분류됩니다.

SpringDocReadController.java
@Tag(name = "User APIs")  
@RestController  
@RequestMapping(value = "/swagger/users")  
public class SpringDocReadController {...}

다음으로, WriteController@Tag 어노테이션을 추가하고 동일한 이름으로 설정합니다. 이를 통해 데이터 변경 요청 관련 API들도 User APIs 그룹으로 분류됩니다.

SpringDocWriteController.java
@Tag(name = "User APIs")  
@RestController  
@RequestMapping(value = "/swagger/users")  
public class SpringDocWriteController {...}

이렇게 하면 SpringDocReadControllerSpringDocWriteController는 스웨거 UI 문서에서 User APIs라는 하나의 그룹으로 통합되어 표시됩니다. 이 방법은 논리적으로 동일한 기능을 하는 API들을 그룹화하여 문서의 가독성과 관리 편의성을 높여줍니다.

documentation-rest-api-with-springdoc_02.png

Request Parameter

요청 파라미터에 대한 설명을 추가하려면 @Parameter 어노테이션을 활용합니다.

SpringDocReadController.java
@GetMapping("/{id}")  
public ResponseEntity<?> userDetailsApi(  
        @Parameter(description = "유저 ID", example = "1") @PathVariable Long id) {...}

documentation-rest-api-with-springdoc_03.png

Request Payload

요청 페이로드 스펙에 대한 설명을 추가하려면 @Schema 어노테이션을 활용합니다.

UserCreateRequest.java
@Schema(description = "유저명", defaultValue = "Ongs", example = "Ongs")  
@NotBlank  
@Size(min = 4, max = 12)  
@Pattern(regexp = "^[a-zA-Z]+$")  
private String username;  
@Schema(description = "생년월일", defaultValue = "2012-08-08", example = "2012-08-08")  
@NotNull  
@PastOrPresent  
private LocalDate birth;  

documentation-rest-api-with-springdoc_04.png

참고로, 요청 페이로드 객체에 Jakarta 패키지의 Validation 어노테이션을 추가한 경우 스웨거에서 자동으로 검증 내용도 문서에 반영합니다. 😲

Request MultipartFile

이미지 또는 문서 파일을 저장할 때 주로 HTTP Content-Type을 multipart/form-data 형식으로 데이터를 전송하고 Spring Controller에서는 MultipartFile 타입으로 바인딩 합니다. 스웨거에서 multipart/form-data를 문서화하려면 @RestControllerconsumes 속성과 SpringDoc의 @Parameter를 활용합니다.

SpringDocWriteController.java
@PostMapping(value = "/avatar", consumes = MULTIPART_FORM_DATA_VALUE, produces = APPLICATION_JSON_VALUE)  
public ResponseEntity<?> userAvatarApi(  
        @Parameter(description = "이미지 파일", content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE))  
        @RequestPart(value = "avatar") MultipartFile avatar) {...}

스웨거 UI의 Request Body 타입이 multipart/form-data로 변경되고 파일을 업로드할 수 있는 버튼이 추가되었습니다.

documentation-rest-api-with-springdoc_05.png

Response Payload

응답 페이로드도 요청 페이로드와 마찬가지로 @Schema 어노테이션을 활용하여 상세 스펙에 대해 설명을 추가합니다.

UserResponse.java
@Schema(description = "유저 ID", example = "1")  
private Long id;  
@Schema(description = "유저명", example = "Ongs")  
private String username;  
@Schema(description = "생년월일", example = "2012-08-08")  
private LocalDate birth;

API 응답은 요청 처리 결과에 따라 서로 다른 구조의 응답 데이터를 작성해야 할 수 있습니다. 이와 같은 경우에 @ApiResponses 어노테이션을 활용하면 HTTP 상태 코드에 따른 응답을 구분하고 이것을 그룹화하여 관리할 수 있습니다.

SpringDocReadController.java
@Operation(summary = "유저 단건 조회 API",  
           description = "요청 파라미터로 전달 받은 유저 ID를 통해 데이터베이스에서 유저 정보를 조회한 후 그 결과를 가공하여 반환합니다.")
@ApiResponses(value = {  
        @ApiResponse(responseCode = "200",  
                     description = "✅ Successful operation",  
                     content = {@Content(schema = @Schema(implementation = UserResponse.class))}),  
        @ApiResponse(responseCode = "400",  
                     description = "⛔ Invalid request",  
                     content = {@Content(schema = @Schema(implementation = RestApiResponse.class))})})  
@GetMapping("/{id}")  
public ResponseEntity<?> userDetailsApi(
        @Parameter(description = "유저 ID", example = "1") @PathVariable Long id) {...}

documentation-rest-api-with-springdoc_06.png

만약, 응답 페이로드가 배열 형태라면 @ArraySchema 어노테이션을 추가합니다.

SpringDocReadController.java
@Operation(summary = "유저 리스트 조회 API",  
           description = "데이터베이스에 저장된 모든 유저를 조회하여 List 타입으로 결과를 반환합니다.")  
@ApiResponses(value = {  
        @ApiResponse(responseCode = "200",  
                     description = "✅ Successful operation",  
                     content = @Content(array = @ArraySchema(schema = @Schema(implementation = UserResponse.class)))),  
        @ApiResponse(responseCode = "400",  
                     description = "⛔ Invalid request",  
                     content = {@Content(schema = @Schema(implementation = RestApiResponse.class))})})
@GetMapping  
public ResponseEntity<?> usersApi() {...}

documentation-rest-api-with-springdoc_07.png


  • Spring
  • Documentation