Java 1.8 + Springboot 2.7.18 + Kotlin에서 Swagger 설정하기

Java와 Spring Boot 및 Kotlin 환경에서 Swagger 설정과 관련된 문제와 해결책을 다룹니다.

이 글에서 해결할 문제

  • Spring Boot 환경에서 Swagger를 설정할 때 발생할 수 있는 일반적인 문제를 이해합니다.
  • Swagger UI에서 파일과 DTO를 동시에 전송하는 과정에서의 에러를 해결합니다.
  • 어렵거나 혼란스러운 Swagger 설정을 명확하게 가이드하여 불필요한 시간 소모를 줄입니다.

실행 환경/전제

  • Java 1.8
  • Spring Boot 2.7.18
  • Kotlin 1.5 이상
  • 프로젝트의 build.gradle.kts에 Swagger 관련 라이브러리 추가
  • Swagger UI의 경로 구성 및 활성화 여부

의존성 추가

먼저, 프로젝트의 build.gradle.kts 파일에 Swagger 관련 의존성을 추가합니다:

implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springdoc:springdoc-openapi-ui:1.8.0")
implementation("org.springdoc:springdoc-openapi-kotlin:1.8.0")

그 다음, application.yml 파일에 Swagger UI의 경로 정보를 설정합니다:

springdoc:
  api-docs:
    path: /documentation/api-docs
  swagger-ui:
    path: /documentation/index.html

증상 재현

Swagger UI를 통해 파일과 DTO를 동시에 전송하려 할 때, 다음과 같은 현상이 발생할 수 있습니다:

  • POST 요청 구조 예시:
@PostMapping("/example")
public ResponseEntity<?> example(
    @RequestPart FileDto dto,
    @RequestPart MultipartFile file) {
    ...
}
  • 사용자가 Swagger UI에서 multipart/form-data 형식으로 요청을 보낼 경우, DTO가 바인딩되지 않거나 다음과 같은 에러가 발생할 수 있습니다:
Could not read document: no String-argument constructor/factory method to deserialize from String value

실패 조건

  • @RequestPart@RequestBody 조합이 잘못 사용될 경우.
  • Swagger UI의 Content-Type 설정이 multipart/form-data로 되어 있지 않은 경우.

원인 분석

Swagger가 자동으로 생성한 요청 스펙에서 파일과 JSON DTO를 동시에 처리하는 데 제약이 있습니다. Springfox의 특정 버전을 사용하고 있을 경우, Swagger 설정이 @RequestBody@RequestPart의 조합에서 혼성이 발생하여 JSON 직렬화 에러가 발생할 수 있습니다.

많은 개발자들이 @RequestPart를 사용하면 Swagger에서 파일과 DTO 모두를 동시에 받아 처리할 것이라 생각하지만, 실제로는 서로 간섭할 수 있다는 점이 상당한 오해를 초래합니다.

해결 절차

이 문제를 해결하기 위한 대표적인 방법은 다음과 같습니다.

1. @RequestPart 대신 @ModelAttribute 활용

@PostMapping("/example")
public ResponseEntity<?> example(
    @ModelAttribute FileDto dto, // DTO
    @RequestPart MultipartFile file // 파일
) {
    ...
}

이 방법을 사용하면 Django Swagger UI에서 DTO의 필드와 파일을 함께 전송할 수 있습니다. 이 경우 파일 필드는 여전히 @RequestPart(혹은 @RequestParam)으로 선언해야 합니다.

2. Swagger 설정에서 @Parameter 또는 @Schema 사용

SpringDoc을 사용하는 경우, DTO 파라미터를 아래와 같이 안내해 주면 Swagger UI에서 올바른 폼 필드를 생성합니다.

@PostMapping("/example")
public ResponseEntity<?> example(
    @Parameter(description = "JSON DTO",
               content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))
    @RequestPart FileDto dto,
    @Parameter(description = "파일 첨부")
    @RequestPart MultipartFile file
) {
    ...
}

3. multipart/form-data 인코딩 설정

컨트롤러에서 파일과 DTO를 동시에 받는 경우, 폼 인코딩이 반드시 multipart/form-data이어야 합니다. Swagger UI의 Try it out 버튼을 사용할 경우 Content-Type이 자동으로 설정되어야 하며, 설정이 잘못된 경우 JSON으로만 인식될 수 있습니다.

검증

해결책을 적용한 후에는 다음과 같이 요청이 성공적으로 처리되는지 확인합니다:

Before

  • 프로그램에서 Swagger UI를 통해 DTO와 파일을 제출하면 “Could not read document: no String-argument constructor/factory method to deserialize from String value”와 같은 에러가 발생.

After

  • 해결책을 적용한 후 Swagger UI에서 DTO와 파일을 동시에 제출할 수 있으며, 정상적으로 요청이 처리되어야 합니다.
  • 성공 판정 기준은 HTTP 200 상태 코드와 함께 올바른 응답 결과가 반환되는 것입니다.

대안 비교

아래 표는 Swagger와 Spring Boot에서 파일과 DTO를 동시 처리하는 방법의 대안 비교입니다.

방법장점단점
@ModelAttributeDTO 수집이 용이하고 Swagger 투명성 보장파일과 DTO 조합 시 복잡성 증가
@Parameter/@Schema구체적인 API 문서화 제공라이브러리 의존도 증가
SpringfoxSwagger UI 사용의 무리 없음특정 버전 문제, 설정 오류 발생 가능

운영 적용 팁

Swagger 관련 설정을 운영에 적용할 때 주의해야 할 점은 다음과 같습니다:

  • Swagger UI의 사용을 서비스로 제한할 수 있는 정책을 수립하여 보안을 강화합니다.
  • Swagger에 대한 사용자 요청 로그를 기록하고, 의심스러운 접근에 대한 모니터링을 강화합니다.
  • 한 번에 많은 요청을 처리할 경우 서버의 성능에 미치는 영향을 체크하며, 필요 시 캐시 전략을 사용할 수 있습니다.

한계와 적용 제외 케이스

  • Swagger UI와 Springfox 조합은 모든 경우에서 완벽한 지원을 제공하지 않습니다. 특정 설정이 필요하며, 이에 대한 이해가 부족할 경우 트러블슈팅에 어려움이 있을 수 있습니다.
  • 다양한 파일 형식이나 복잡한 DTO를 동시에 처리해야 할 때, 추가적인 손실이 발생할 수 있습니다.

마무리

Swagger 설정을 통해 파일과 DTO를 동시에 전송하는 문제를 해결하는 체크리스트는 다음과 같습니다:

  1. Swagger 관련 라이브러리가 설치되어 있는지 확인합니다.
  2. Swagger UI에서 API 문서가 정상적으로 생성되는지 확인합니다.
  3. 각 요구 사항에 맞는 어노테이션이 사용되었는지 점검합니다.
  4. Content-Type이 올바르게 설정되어 요청이 처리되는지 검토합니다.
  5. 파일과 DTO가 정상적으로 전송되는지 확인합니다.

요약

  • 핵심 배경을 한 줄로 정리
  • 적용 기준/선택 이유 정리
  • 운영 시 점검 포인트 정리

구현 포인트

구현 시 바로 적용 가능한 포인트를 정리합니다.

예시 코드

implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springdoc:springdoc-openapi-ui:1.8.0")
implementation("org.springdoc:springdoc-openapi-kotlin:1.8.0")

주의사항/트레이드오프

  • 운영/보안 관점의 리스크를 점검합니다.
  • 성능/유지보수 트레이드오프를 정리합니다.

© 2024. Chiptune93 All rights reserved.