💐 Spring

Springdoc을 이용한 API 문서 자동화 (Swagger, SpringBoot 3.x)

2023. 6. 8. 21:30
목차
  1. 의존성 추가
  2. 설정 파일
  3. application.yml 설정
  4. Spring Security를 사용하고 있다면?
  5. Javadoc 으로 문서를 꾸며보자
  6. Authorization 추가
  7. 공통 Pageable 응답 어노테이션 개발
  8. 공통 API 응답 어노테이션 개발
  9. Controller 명세
  10. REFERENCES
반응형

Spring Boot 3.x.x 부터는 JavaEE → Jakarta EE로 교체되었습니다.

그렇기 때문에 이전에 사용했던 Springfox는 현재 Spring Boot 3.x.x에 대한 업데이트가 이뤄지지 않고 현시점에는 사용할 수 없었습니다. Springdoc 공식문서에서 어떻게 적용할 수 있는지에 대한 자세한 방법이 나와있으니 참고하시면 좋을 것 같습니다.

springdoc-openapi v2.0.2

의존성 추가

Spring Boot 3.x.x부터는 아래 의존성을 추가해주면 Swagger-ui 설정은 끝입니다.

implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2"
  • springdoc-openapi-ui → springdoc-openapi-starter-webmvc-ui 로 교체되었습니다.
  • springdoc-openapi-webflux-ui → springdoc-openapi-starter-webflux-ui 로 교체되었습니다.

해당 의존성을 추가해주는 것만으로도 /swagger-ui.html 접근이 가능합니다.

설정 파일

현재 API 문서의 설명이나, 버전 등등 더 세부적으로 설정해줄 순 없을까요?

바로 OpenApi를 빈으로 등록하는 방법이 있습니다.

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class SpringdocConfig {

    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
                .addOpenApiCustomizer(openApi -> openApi
                        .info(new Info().title("TEST API DOCS")
                                .description("테스트 API 문서입니다.")
                                .version("v1.0"))
                .group("Test Group")
                .packagesToScan("org.example.controller")
                .displayName("This is Test API")
                .build();
    }
}

application.yml 설정

springdoc:
  packages-to-scan: org.example.controller
  default-consumes-media-type: application/json;charset=UTF-8
  default-produces-media-type: application/json;charset=UTF-8
  swagger-ui:
    path: /docs/test.html
    tags-sorter: alpha
    operations-sorter: alpha
		syntax-highlight:
      activated: true
  api-docs:
    path: /v3/docs
    groups:
      enabled: true
  cache:
    disabled: true
  • springdoc.swagger-ui.tags-sorter: URI를 다음 기준으로 정렬
  • springdoc.swagger-ui.operations-sorter : HTTP 메소드를 다음 기준으로 정렬
    • alpha: 알파벳 순으로 정렬
    • method: HTTP 메소드 순으로 정렬

더 많은 properties 설정은 공식문서에서 확인하시길 바랍니다.

Spring Security를 사용하고 있다면?

implementation 'org.springdoc:springdoc-openapi-security:1.6.14'

이미 springdoc-openapi-starter-webmvc-ui 의존성을 사용중이라면, 따로 의존성을 추가해줄 필요는 없습니다. 우리가 추가해줬던 의존성으로 인해 @AuthenticationPrincipal 어노테이션은 자동으로 swagger-ui에 ignore 되므로 따로 처리해주지 않아도 됩니다.

Javadoc 으로 문서를 꾸며보자

springdoc-openapi-starter-webmvc-ui 의존성을 사용중이라면, 아래 의존성들을 추가해줘서 javadoc을 활성화 시켜줘야 합니다.

annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.13.0'
implementation 'com.github.therapi:therapi-runtime-javadoc:0.13.0'

이제 작성한 javadoc은 다음과 같이 처리됩니다.

  • method comment: @Operation(description={}) 으로 치환됩니다.
  • @return: @Operation(response={}) 으로 치환됩니다.
  • attribute comment: @Schema(description={}) 으로 치환됩니다.
💡 만약 Swagger Annotation과 javadoc이 동시에 존재한다면, Swagger Annotation이 우선으로 적용됩니다.

Authorization 추가

JWT를 사용해 인가를 하고있다면 다음과 같이 설정을 추가하면 Swagger에서 전역 인증정보를 설정하여 인증이 필요한 API를 호출할 수 있습니다.

@Configuration
public class SpringdocConfig {

    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
                .addSecurityItem(new SecurityRequirement().addList("Authorization"))
                .components(new Components().addSecuritySchemes("Authorization", new SecurityScheme()
                        .name("Authorization")
                        .type(SecurityScheme.Type.HTTP)
                        .scheme("bearer")
                        .bearerFormat("JWT")))
                .addOpenApiCustomizer(openApi -> openApi
                        .info(new Info().title("TEST API DOCS")
                                .description("테스트 API 문서입니다.")
                                .version("v1.0"))
                .group("Test Group")
                .packagesToScan("org.example.controller")
                .displayName("This is Test API")
                .build();
    }
}

공통 Pageable 응답 어노테이션 개발

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Parameters({
        @Parameter(name = "page", description = "페이지 번호 (0..N) [기본값: 0]", schema = @Schema(type = "integer", defaultValue = "0", nullable = true)),
        @Parameter(name = "size", description = "페이지 번호 (0..100) [기본값: 10]", schema = @Schema(type = "integer", defaultValue = "10")),
        @Parameter(name = "sort", description = "정렬 (컬럼,asc|desc) [예시] 이름을 내림차순 정렬 ex) 'name,desc'", schema = @Schema(type = "array", name = "정렬 (컬럼,asc|desc) [예시] 이름을 내림차순 정렬 ex)")),
        @Parameter(name = "pageable", hidden = true)
})
public @interface ApiPageable {
}

공통 API 응답 어노테이션 개발

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ApiResponse(responseCode = "401", description = "UnAuthorized", useReturnTypeSchema = true, content = @Content(schema = @Schema(implementation = YourExample.class), mediaType = APPLICATION_JSON_VALUE, examples = @ExampleObject(value = "example")))
@ApiResponse(responseCode = "403", description = "Forbidden", useReturnTypeSchema = true, content = @Content(schema = @Schema(implementation = YourExample.class),mediaType = APPLICATION_JSON_VALUE, examples = @ExampleObject(value = "example")))
@ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content(schema = @Schema(implementation = YourExample.class)))
public @interface ApiCommonResponse {
}

Controller 명세

GET 방식

@Operation(
        summary = "회원 조회 API",
        description = "회원을 조회할 수 있습니다.",
        responses = {
                @ApiResponse(responseCode = "200", description = "Success", useReturnTypeSchema = true, headers = @Header(name = "Authorization", required = true), content = @Content(schema = @Schema(implementation = YourExample.class), mediaType = APPLICATION_JSON_VALUE, examples = @ExampleObject(value = "example"))),
                @ApiResponse(responseCode = "404", description = "NotFound", useReturnTypeSchema = true, content = @Content(schema = @Schema(implementation = YourExample.class), examples = @ExampleObject(value = "example"))),})
@Parameters({
        @Parameter(name = "username", description = "사용자 이름", example = "john", required = true),
        @Parameter(name = "age", description = "사용자 나이", example = "20", required = true)
})
@ApiPageable
@ApiCommonResponse
@GetMapping("/members")
ResponseEntity<MemberDto> searchMembers(
        @RequestParam("username") String username,
        @RequestParam("age") int age,
        @PageableDefault Pageable pageable
){
	...
}

POST 방식

@Operation(summary = "회원을 생성하는 API",
        requestBody = @RequestBody(description = "회원 생성을 위한 DTO"),
        responses = {
                @ApiResponse(responseCode = "200", description = "Success", useReturnTypeSchema = true, headers = @Header(name = "Authorization", required = true), content = @Content(schema = @Schema(implementation = CreateProjectResponse.class), mediaType = APPLICATION_JSON_VALUE, examples = @ExampleObject(value = "{\\"success\\":true,\\"error\\":null,\\"message\\":{\\"projectId\\":1}"))),
                ...
        })
@ApiCommonResponse
ResponseEntity<Long> createProject(
        @Valid @RequestBody CreateMemberDto request
) {
	...
}

 

 

REFERENCES

 

springdoc-openapi v2.1.0

springdoc-openapi java library helps to automate the generation of API documentation using spring boot projects. springdoc-openapi works by examining an application at runtime to infer API semantics based on spring configurations, class structure and vario

springdoc.org

 

Set JWT with Spring Boot and Swagger UI | Baeldung

Learn how to set a JSON Web Token on requests to Swagger UI running in Spring Boot.

www.baeldung.com

반응형
저작자표시 (새창열림)
  1. 의존성 추가
  2. 설정 파일
  3. application.yml 설정
  4. Spring Security를 사용하고 있다면?
  5. Javadoc 으로 문서를 꾸며보자
  6. Authorization 추가
  7. 공통 Pageable 응답 어노테이션 개발
  8. 공통 API 응답 어노테이션 개발
  9. Controller 명세
  10. REFERENCES
'💐 Spring' 카테고리의 다른 글
  • [Spring] - ConfigurationProperties를 통해 프로퍼티 주입하기 (feat. @Value 상위 호환)
  • Spring Validation을 통해 데이터 유효성 검증하기
  • Spring-Boot REST Docs 적용기 (with. Gradle, Maven)
  • Optional 값이 있을 때 Exception 처리
iseunghan
iseunghan
꾸준하게 열심히..
iseunghan꾸준하게 열심히..
iseunghan
iseunghan

공지사항

  • 어제보다 나은 오늘이 되기 위해 🔥
  • 분류 전체보기 (262)
    • 💐 Spring (14)
      • 개념 및 이해 (2)
      • Spring 핵심 기술 (24)
      • Spring REST API (8)
      • Spring MVC, DB 접근 기술 (7)
      • Spring Security (23)
      • Spring in Action (1)
    • 🌻 JAVA (84)
      • 자바 ORM 표준 JPA 프로그래밍 (20)
      • 알고리즘, 자료구조 (13)
      • 디자인 패턴 (7)
      • 정리정리정리 (43)
      • JUnit (1)
    • 🔖 Snippets (3)
      • Javascript (3)
    • ⚙️ Devops (22)
      • ⛏ Git (11)
      • 🐳 Docker (6)
      • 🐧 Linux (3)
      • 🌈 Jenkins (1)
      • 📬 Kafka (1)
    • 💬 ETC.. (4)
      • 💻 macOS (2)
    • 🌧️ ORM (2)
      • JPA (2)
    • 🐍 Python (3)
    • 📚 Databases (15)
      • 오라클로 배우는 데이터베이스 개론과 실습(2판) (3)
      • RealMySQL 8.0 (8)
    • 🔥 Computer Science (5)
      • 📡 네트워크 (5)
    • 🏷️ 협업 (1)
    • 📜 코딩테스트 (38)
      • BAEKJOON\수학 1, 수학 2 (8)
      • BAEKJOON\재귀 (5)
      • BAEKJOON\브루트 포스 (3)
      • BAEKJOON\정렬 (1)
      • BAEKJOON\백트래킹 (5)
      • BAEKJOON\BFS, DFS (6)
      • BAEKJOON\이분탐색 (1)
      • BAEKJOON\다이나믹 프로그래밍 (9)
      • BAEKJOON\그리디 알고리즘 (0)
    • ✨ ISEUNGHAN (1)

인기 글

최근 글

전체
오늘
어제
반응형
hELLO · Designed By 정상우.
iseunghan
Springdoc을 이용한 API 문서 자동화 (Swagger, SpringBoot 3.x)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.