Framework & Library/Spring

spring boot 3.x.x swagger 설정 및 file upload 문제 해결

ruu++ 2024. 4. 17. 17:40

1. Gradle 의존성 추가

//GRADLE 의존성
// https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui  
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.2.0'

2. 스웨거 적용

swaggerConfig 클래스 생성

//SwaggerConfig
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 

@Configuration  
public class SwaggerConfig {  

    private final String REST_API_ROOT = "/api/**";
    private final String REST_API_GROUP = "REST API";

    private final String COMMON_API_ROOT = "/**/*";
    private final String COMMON_API_GROUP = "COMMON API";
    private final String[] COMMON_EXCLUDE_ROOT = {"/api/**/*"};

    @Bean
    public GroupedOpenApi restApi(){

        return GroupedOpenApi.builder()
            .pathsToMatch(REST_API_ROOT)
            .group(REST_API_GROUP)
            .build();
    }

    @Bean
    public GroupedOpenApi commonApi(){

        return GroupedOpenApi.builder()
            .pathsToMatch(COMMON_API_ROOT)
            .pathsToExclude(COMMON_EXCLUDE_ROOT)
            .group(COMMON_API_GROUP)
            .build();
    }
}

Controller에서 사용

//... 다른 어노테이션들
@Tag(name = "BoardController")
public class Cotnroller{

    //Rest 형식이 아닌 일반 컨트롤러에서 스웨거 사용
    @GetMapping("/list")
    //해당 어노테이션이 존재하지않으면 레스트풀 형식이 아닌 API는 SWAGGER UI 에 등록되지 않습니다.
    @Operation(summary = "리스트")  
    public void list(){
    }
}
  • @Tag(name = "BoardController") <- 클래스 TYPE에 적용되는 어노테이션
    • 스프링 부트 2.7에서 사용법은 @api -> @Tag로 변경

Swagger UI 확인

{개발 환경의 주소}/swagger-ui/index.html

3. 파일 MultiPartFile 관련 문제점

  • 파라미터로 파일 데이터 전송을 위한 DTO를 사용할 경우 multipart형식으로 Swagger-ui에서 파일을 보내 테스트 할 수 없는 문제가 발생했습니다.
  • 해결방법
    • 스웨거에서 제공하는 @Parameter 어노테이션을 이용합니다.

Controller

@Operation(summary = "파일 등록", description = "멀티파트 타입 데이터로 전송") 
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) 
public ResponseEntity<UploadResponseDTO> upload(@Valid @Parameter( 
content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE) ) UploadFileDTO uploadFileDTO)
@Operation(summary = "파일 수정", description = "멀티파트 타입 데이터로 전송")  
@PutMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)  
public ResponseEntity changeUpload(@Valid @Parameter(  
content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE)  
) UploadFileDTO uploadFileDTO)

4. refector

  • @Parameter 필드 중에 @Content을 사용하여 파라미터의 ContentType을 지정하여 처리합니다
  • 하지만, 해당 어노테이션에 의해 파라미터 부분의 코드 가독성이 좋지 않습니다.
  • 파일 관련 처리에서 재사용을 위해서 분리가 필요하다고 생각했습니다.
  • 파라미터에 적용할 어노테이션을 새로 만들어서 사용합니다.

FilesParameter Annotation

import io.swagger.v3.oas.annotations.Parameter; 
import io.swagger.v3.oas.annotations.media.Content; import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
import org.springframework.http.MediaType;

@Target({ElementType.PARAMETER})  
@Retention(RetentionPolicy.RUNTIME)  
@Parameter(  
content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE)  
)  
public @interface FilesParameter {

}

Controller

@Operation(summary = "파일 등록", description = "멀티파트 타입 데이터로 전송")  
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)  
public ResponseEntity<UploadSavedDTO> upload(@Valid @FilesParameter UploadFileDTO uploadFileDTO)

@Operation(summary = "파일 수정", description = "멀티파트 타입 데이터로 전송")  
@PutMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)  
public ResponseEntity<UploadSavedDTO> changeUpload(@Valid @FilesParameter UploadFileDTO uploadFileDTO)

👏👏👏 동작 확인

  • 파일이 제대로 등록되는 것을 확인했습니다!.

 

번외. 운영환경에서 Swagger-ui 비활성화하기

1. application.properties

springdoc.swagger-ui.enabled=false

 

2. application.yml

springdoc:
  swagger-ui:
    enabled: false

시큐리티까지 적용하려면 해당 영상을 참고해주세요.

  1. Boot 3 + security + swwager 3

참고 영상