[Project] Swagger 적용 (springdoc)

김지현·2023년 11월 27일
0

Spring Boot 프로젝트

목록 보기
6/20

Swagger는 REST API를 문서화하고 사용자가 쉽게 테스트할 수 있도록 도와주는 도구이다. 개발자가 문서를 직접 작성하지 않아도 되며 API 버전 관리가 용이해진다는 장점을 가지고 있다.
Spring Boot 프로젝트에 Swagger UI를 적용하는 라이브러리에는 springfox와 springdoc가 있는데 springfox의 경우에는 2020년 7월 이후로 업데이트가 되지 않아 최근에는 springdoc를 사용하는 것이 선호된다고 한다.

0. 프로젝트 환경

  • Intellij Ulitmate
  • Spring Boot 3.1.5
  • JDK 17
  • Springdoc Openapi UI 2.1.0
  • Spring Security

1. 의존성 추가

bulid.gradle에 springdoc openapi 의존성을 추가한다.

// swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'

2. Swagger config 설정

swagger config 클래스에서 API 문서페이지에 대한 설명을 작성한다.

@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI openAPI() {
        Info info = new Info()
                .version("v1.0.0")
                .title("News Feed 프로젝트 테스트");
                .description("취준생을 위한 New Feed 프로젝트 swagger UI 테스트")

        return new OpenAPI()
                .info(info)
    }
}

3. JWT 인증

스프링 시큐리티가 적용된 프로젝트에서 기능 테스트를 위해서는 JWT 토큰 인증이 필요하다. swagger에서 해당 테스트를 진행하기 위해서는 swagger config의 OpenAPI Bean에 JWT 설정을 추가해주어야한다. (JWT 설정은 V1도 가능하고 V2도 가능하다)

@Bean
    public OpenAPI openAPI() {
        Info info = new Info()
                .version("v1.0.0")
                .title("News Feed 프로젝트 테스트");

		// JWT V1
        String jwt = "JWT";
        SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
        Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
                .name(jwt)
                .type(SecurityScheme.Type.HTTP)
                .scheme("bearer")
                .bearerFormat("JWT")
        );
        
        // JWY V2
        SecurityScheme securityScheme = new SecurityScheme()
            .type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")
            .in(SecurityScheme.In.HEADER).name("Authorization");
        SecurityRequirement securityRequirement = new SecurityRequirement().addList("bearerAuth");

        return new OpenAPI()
                .info(info)
                .addSecurityItem(securityRequirement)
                .components(components);
    }

또한 WebSecurityConfig에 swagger 경로 접근을 허용하도록 설정해준다.

httpSecurity.authorizeHttpRequests(auth -> auth
            .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
            .anyRequest().authenticated());

이렇게 설정해주면 swagger 문서 상단에 Authorize 버튼이 생성되고 Value 값을 넣어주면 로그인 상태로 테스트가 가능하다.

4. Annotation

여기까지만 설정해도 기본적인 swagger 문서 확인과 테스트가 가능하다. 프로젝트 실행 후 http://localhost:8080/swagger-ui/index.html#/ 로 접속하면 확인할 수 있다. 다만 기본 설정만으로는 api 기능을 한 눈에 알아보기 어렵다. springdoc-openapi 라이브러리에서는 각 api에 대한 부연설명, 파라미터, 응답 형식 지정 등을 위한 다양한 애너테이션을 제공한다.

@Tag : operation 그룹 설정
@Schema : 스키마 설정
@Opearion : API 상세 정보 설정
@ApiResponse : 응답 설정
@Parameter : 파라미터 설정

@Tag

name : 이름
description : 부연 설명

@Tag는 API들을 하나의 API 그룹으로 묶어주며 주로 Controller 영역에 설정한다.

@Tag(name = "POST", description = "게시글 API")
public class PostController {

@Schema

description : 이름
defaultvalue : 기본값
allowableVaules : 허용 가능한 값

@Schema로 Request body로 입력되어야 할 값들에 대한 정의와 설명이 가능하다.

@Size(max = 30, message = "제목은 최대 30자까지 작성 가능합니다.")
    @Schema(description = "제목")
    private String title;

@Operation

summary : API 이름
description : 상세 설명

@Operation으로 API 동작에 대한 명세를 작성할 수 있다. 컨트롤러 메서드에 설정한다.

    @Operation(summary = "뉴스피드 페이지", description = "모든 포스트를 팔로우, 좋아요, 작성일에 따라 계산된 가중치로 정렬하여 조회")
public ResponseEntity<BaseResponse<Page<PostResponseDto>>> getAllPosts(){

@ApiResponse

responseCode : http 상태 코드
description : 응답에 대한 설명
content : payload
schema : payload에서 이용하는 스키마
hidden : 스키마 숨김 여부
implementaion : 스키마 대상 클래스
ExampleObject : 응답 예시 값 지정

@ApiResponse으로 응답 값을 설정할 수 있다. swagger 기본 값은 200 OK에 대한 응답 예시만 보여주므로 성공, 실패 시의 응답 예시를 모두 보여주도록 설정하면 좋다. 여러 개의 응답일 경우 @ApiResponses로 묶을 수 있다.

@ApiResponses({
     @ApiResponse(responseCode = "200", description = "선택 포스트 조회"),
     @ApiResponse(responseCode = "400", description = "포스트가 존재하지 않습니다",
         content = @Content(
               schema = @Schema(implementation = BaseResponse.class),
                    examples = @ExampleObject(
                         name = "ResponseEntity<BaseResponse<Void>>",
                         value = "{\"success\": false, \"message\": \"에러 메세지\", \"payload\": null}"
                            )
                    ))
    })

@Parameter

description : 설명
name : 파라미터 이름
in : 파라미터 위치 (query, header, path, cookie)

@Parameter는 파라미터에 대한 설명을 추가한다. 파라미터 앞에 설정하거나 메서드 위의 영역에서 @Parameters로 묶어서 설정할 수 있다.

@Parameters({
            @Parameter(description = "페이지 번호", name = "page"),
            @Parameter(description = "한 페이지의 포스트 수", name = "size")
    })
    @GetMapping
    public ResponseEntity<BaseResponse<Page<PostResponseDto>>> getAllPosts(
    	@RequestParam("page") int page, 
    	@RequestParam("size") int size) {

0개의 댓글