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를 동시 처리하는 방법의 대안 비교입니다.
| 방법 | 장점 | 단점 |
|---|---|---|
@ModelAttribute | DTO 수집이 용이하고 Swagger 투명성 보장 | 파일과 DTO 조합 시 복잡성 증가 |
@Parameter/@Schema | 구체적인 API 문서화 제공 | 라이브러리 의존도 증가 |
| Springfox | Swagger UI 사용의 무리 없음 | 특정 버전 문제, 설정 오류 발생 가능 |
운영 적용 팁
Swagger 관련 설정을 운영에 적용할 때 주의해야 할 점은 다음과 같습니다:
- Swagger UI의 사용을 서비스로 제한할 수 있는 정책을 수립하여 보안을 강화합니다.
- Swagger에 대한 사용자 요청 로그를 기록하고, 의심스러운 접근에 대한 모니터링을 강화합니다.
- 한 번에 많은 요청을 처리할 경우 서버의 성능에 미치는 영향을 체크하며, 필요 시 캐시 전략을 사용할 수 있습니다.
한계와 적용 제외 케이스
- Swagger UI와 Springfox 조합은 모든 경우에서 완벽한 지원을 제공하지 않습니다. 특정 설정이 필요하며, 이에 대한 이해가 부족할 경우 트러블슈팅에 어려움이 있을 수 있습니다.
- 다양한 파일 형식이나 복잡한 DTO를 동시에 처리해야 할 때, 추가적인 손실이 발생할 수 있습니다.
마무리
Swagger 설정을 통해 파일과 DTO를 동시에 전송하는 문제를 해결하는 체크리스트는 다음과 같습니다:
- Swagger 관련 라이브러리가 설치되어 있는지 확인합니다.
- Swagger UI에서 API 문서가 정상적으로 생성되는지 확인합니다.
- 각 요구 사항에 맞는 어노테이션이 사용되었는지 점검합니다.
- Content-Type이 올바르게 설정되어 요청이 처리되는지 검토합니다.
- 파일과 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")
주의사항/트레이드오프
- 운영/보안 관점의 리스크를 점검합니다.
- 성능/유지보수 트레이드오프를 정리합니다.