[Spring Boot] Springdoc-openapi Swagger 적용 (+ JWT 사용 시 적용법)

2023. 10. 4. 15:40기술 창고/Spring

728x90
SMALL

백엔드 개발 후 프론트와 원활한 협업을 위해 Api 문서화 작업이 필요합니다.

따라서 가장 흔히 볼 수 있는 Swagger를 적용하는 방법에 대해서 알아보겠습니다.

 

! 저는 gradle 환경입니다.

 

1. Build.Gradle 디펜던시 import

// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'

Swagger 디펜던시를 받아줍니다.

Swagger에는 Springdoc, Springfox 이 두 가지가 대표적으로 있는 것으로 알고있는데 Springdoc 를 사용해야 하는 것이 좋습니다.

Springdoc는 지속적으로 오늘날까지 계속 지원해주고 업데이트되고 있지만 Springfox의 경우에는 업데이트가 중단된지 오래입니다.

 

 

2. application.properties 파일 설정

# swagger-ui custom setting
springdoc.swagger-ui.path=/swagger-ui.html
springdoc.swagger-ui.groups-order=DESC
springdoc.swagger-ui.operations-sorter=method
springdoc.swagger-ui.disable-swagger-default-url=true
springdoc.swagger-ui.display-request-duration=true

springdoc.api-docs.path=/v3/api-docs
springdoc.show-actuator=true
springdoc.default-consumes-media-type=multipart/form-data
#springdoc.default-produces-media-type=multipart/form-data
springdoc.default-produces-media-type=application/json
springdoc.paths-to-match=/miml/**

 

여기서 저는 개발 중인 api에 MultiPartFile 형식의 요청 데이터가 존재하므로 default-consumes-media-type 은 Multipart/form-data 로 지정해주었습니다.

 

default-produces-media-type 은 기존적으로 제공하는 데이터의 형식을 지정해주는 부분으로서 application/json 으로 지정해주었습니다.

 

또한 paths-to-match 에는 제가 개발한 api의 최상의 경로를 넣어주었습니다.

자신이 개발하고있는 api들의 최상위 경로로 넣어주시면 됩니다.

 

 

3. SwaggerConfig 설정 클래스 파일 생성

package music.is.my.life.musicismylife.configuration;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SecurityScheme(
        name = "Bearer Authentication",
        type = SecuritySchemeType.HTTP,
        bearerFormat = "JWT",
        scheme = "bearer"
)
@OpenAPIDefinition(
        info = @Info(title = "EDM 플랫폼 서비스 API 명세서",
                description = "EDM 아티스트들을 위한 커뮤니티형 음원 공유 플랫폼",
                version = "v3"))
@RequiredArgsConstructor
@Configuration
public class SwaggerConfig {

    @Bean
    public GroupedOpenApi chatOpenApi() {
        String[] paths = {"/miml/**"};

        return GroupedOpenApi.builder()
                .group("EDM 플랫폼 API v3")
                .pathsToMatch(paths)
                .build();
    }
}

Swagger 설정 파일을 만들어줍니다.

Bean으로 지정한 GroupedOpenApi 에는 builder를 통해 Swagger로 접속할 시 타이틀로 뽑히게 될 group을 지정해주고, pathsToMatch에는 api들의 잡아준 최상위 경로를 넣어줍니다.

이외에 추가적인 설정도 할 수 있습니다.

 

@SecurityScheme 

- 프로젝트에 Spring Security와 JWT를 적용함으로서 Swagger 요청 시 필요한 Token 여부 확인을 위해 토큰 정보를 명시하는 보안 확인 어노테이션

!! 이 어노테이션을 지정하여 Config 파일을 만든 뒤 api에 @SecurityRequirement(name = "Bearer Authentication") 어노테이션을 적용하면 JWT가 필요한 api들에 JWT 토큰을 사용할 수 있도록 적용됩니다.

이후에 보여드리겠지만 Swagger에 자물쇠 형식의 이모티콘이 나오는 것을 볼 수 있을 것입니다.

 

@OpenAPIDefinition

- info 에 Swagger 접속 시 상위에 나타나게 될 Swagger 문서의 타이틀 및 버전, 설명 정보 명시 어노테이션

 

 

4. Controller 마다 Swagger가 적용될 API 들에 대한 어노테이션 적용

이제 초기 세팅 설정은 완료되었으니 각 API들에 Swagger 관련 어노테이션을 붙여 적용시키면 됩니다.

이 작업을 진행하게 될 때 JWT의 여부, 요청 데이터들의 타입에 따라 설정들이 달라지므로 이 점을 유의하여 정리해보겠습니다.

 

(1) API 요청 데이터에 HttpServletRequest, Json 데이터, MultiPartFile 데이터가 존재할 경우

// 음악 등록 api
@Operation(summary = "음악 등록 요청", tags = { "Music Controller" })
@SecurityRequirement(name = "Bearer Authentication")
@ApiResponses({
        @ApiResponse(responseCode = "200", description = "OK",
                content = @Content(schema = @Schema(implementation = ResponseBody.class))),
        @ApiResponse(responseCode = "400", description = "BAD REQUEST"),
        @ApiResponse(responseCode = "404", description = "NOT FOUND"),
        @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR")
})
@PostMapping(value = "/upload", consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<ResponseBody> musicUpload(
        HttpServletRequest request,
        @Parameter(description = "업로드 공통 내용") @RequestPart(value = "uploadInfo") MusicUploadRequestDto musicUploadRequestDto, // 공통적으로 들어갈 업로드 정보들
        @Parameter(description = "각 곡마다 추가 업로드 내용") @RequestPart(value = "uploadInfo2") List<MusicUpload2RequestDto> musicUpload2RequestDtos, // 업로드 시 각 업로드 곡에 대한 변경값 요청 객체 (예 : 곡 제목) - 정보를 바꾸지 않는 다면 아예 변수 자체를 보내지 않는 것이 아니라 빈 칸으로 보내야 한다.
        @Parameter(description = "음악 파일들") @RequestPart(value = "musics") List<MultipartFile> musics, // 업로드 하고자 하는 음악 파일들
        @Parameter(description = "썸네일 이미지 파일") @RequestPart(value = "thumbImg") MultipartFile thumbnailImg) // 업로드 하는 음악 및 앨범에 대한 썸네일 이미지 파일
        throws IOException, CannotReadException, TagException, InvalidAudioFrameException, ReadOnlyFileException {
    log.info("음악 등록 api");

    return musicService.musicUpload(request, musicUploadRequestDto, musicUpload2RequestDtos, musics, thumbnailImg);
}

(1) @Operation(summary = "", tags = {""})

해당 어노테이션은 api의 타이틀을 명시하거나, api를 공통적으로 묶는 controller를 명시해줄 수 있습니다.

 

- summary 속성 : api타이틀

 

- tags 속성 : controller 그룹

 

 

(2) @SecurityRequirement(name = "")

SwaggerConfig에 설정한 토큰 사용 설정 어노테이션을 불러와 api에 토큰을 사용할 수 있도록 적용하는 어노테이션

 

- name 속성 : SwaggerConfig 에서 설정한 토큰 명을 명시하여 사용하도록 명시

Swagger api에 오른쪽 부분에 자물쇠 이모티콘이 나오는 것을 볼 수 있습니다.

해당 자물쇠를 누르면 토큰 값을 입력할 수 있는 입력 폼이 나오게 됩니다.

 

 

(3) @ApiResponses({
      @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementaion = ResponseBody.class))),

      @ApiResponse(responseCode = "400", description = "BAD REQUEST"),

      @ApiResponse(responseCode = "404", description = "NOT FOUND"),

      @ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR")
})

해당 어노테이션은 Swagger에서 Api를 테스트 실행했을 때 (try it out) 응답에 따라 결과를 구분해주는 어노테이션입니다.

 

- responseCode : 상태 결과 코드

- description : 상태 결과 설명

- content : 결과 반환 시 보여줄 결과 내용 (Schema = 스키마를 ResponseBody.class 로 파싱하여 보여줍니다.) 

상태 결과 구분

 

content 노출 스키마

 

 

(4) @PostMapping(value = "", consumes = { MediaType.APPLICATION_JSON_VALUE , MediaType.MULTIPART_FORM_DATA_VALUE }, produces = {MediaType.APPLICATION_JSON_VALUE})

이 어노테이션은 api의 method를 명시하는 어노테이션으로써 PostMapping은 데이터 생성, 등록과 같은 post method를 요청받고, GetMapping은 데이터를 조회하는 get method, DeleteMapping은 데이터를 삭제하는 delete method, PutMapping / PatchMapping은 데이터를 수정하는 update method를 요청받습니다.

 

- value : api 요청 url

- consumes = {} : api를 요청할 시 요청받는 데이터들의 타입을 명시 하는 속성, 해당 속성을 명시하지 않고 요청하면 에러가 발생합니다.

( MediaType.APPLICATION_JSON_VALUE - JSON 타입 요청 데이터 , MediaType.MULTIPART_FORM_DATA_VALUE - MultiPartFile 타입 요청 데이터)

- produces = {} : 결과를 반환할 시 해당 반환 데이터의 타입

( MediaType.APPLICATION_JSON_VALUE - JSON 타입 반환 데이터 )

 

 

(5) 

@Parameter(description = "업로드 공통 내용") @RequestPart(value = "uploadInfo") MusicUploadRequestDto musicUploadRequestDto, 
@Parameter(description = "각 곡마다 추가 업로드 내용") @RequestPart(value = "uploadInfo2") List<MusicUpload2RequestDto> musicUpload2RequestDtos,
@Parameter(description = "음악 파일들") @RequestPart(value = "musics") List<MultipartFile> musics, 
@Parameter(description = "썸네일 이미지 파일") @RequestPart(value = "thumbImg") MultipartFile thumbnailImg

Parameter 어노테이션은 요청하는 변수 파라미터를 Swagger 상에서 인식할 수 있도록 지정해주는 어노테이션 입니다.

RequestPart 어노테이션은 요청 데이터 변수를 실제로 받기 위한 어노테이션입니다.

 

- description : 파라미터에 대한 설명

- value : 실제로 요청받는 데이터들에 대한 명칭

현재 이 api는 HttpServletRequest 요청을 포함한 요청 데이터가 5개가 존재합니다.

각각 uploadInfo는 json 형식의 단일 데이터,

uploadInfo2는 json 형식의 다중 배열 데이터,

musics는 MultiPartFile 형식의 다중 배열 데이터,

thumbImg는 MultiPartFile 형식의 단일 데이터를 받고있습니다.

 

이처럼 필요한 Swagger 관련 어노테이션을 적용 완료했으면 Swagger로 확인을 해보면 됩니다.

- Swagger 주소 : http://localhost:8080/swagger-ui/index.html

 

Swagger에 접속해서 현 api를 실행해서 정상적으로 결과가 반환되면 아까 ApiResponse 어노테이션으로 설정한 정상 상태 결과가 나오게 됩니다.

 

 

 

시나리오

(1) Build.Gradle 디펜던시 import

(2) application.properties 파일 설정

(3) SwaggerConfig 설정 클래스 파일 생성 (JWT를 사용한다면 @SecuritySchema 추가)

(4) Controller 마다 Swagger가 적용될 API 들에 대한 관련 어노테이션 적용 (JWT가 필요한 api마다 @SecurityRequirement로 Config에서 설정한 토큰 name으로 가져와서 토큰 적용)

(5) Swagger 실행 후 api 테스트 실행

 

728x90
반응형
LIST