이미지를 지원하지 않는 Swagger를 만들기 위한 의존성
spring-restdocs-mockmvc
의 MockMvc
클래스를 활용하여 컨트롤러 테스트 코드를 작성하고 그 결과를 restdocs-api-spec
와 swagger.generator
를 활용하여 Swagger를 만들어 왔습니다.
하지만 해당 방법을 활용하면서 multipart/form-data
요청의 경우 요청 스펙을 정의할 수 없다는 문제가 있었습니다.
org.springframework.restdocs.payload.PayloadHandlingException: Cannot handle multipart/form-data content as it could not be parsed as JSON or XML
공식 문서를 확인해 본 결과 이는 Swagger를 만들기 위해서 활용하는 의존성에서 지원을 하지 않는 것이지 Swagger에서 multipart/form-data
을 지원하지 않는 것은 아니었습니다.
요청의 스펙을 정의하는 곳은 어딜까?
컨트롤러 테스트를 통해 Swagger를 만드는 과정
spring-restdocs-mockmvc
로 컨트롤러 테스트 수행- 테스트 결과를
restdocs-api-spec
로 openapi 형식으로 전환 - openapi 형식의 파일을 기반으로
swagger.generator
활용 Swagger 생성
위의 과정을 파악하며 restdocs-api-spec
가 테스트 결과를 통해 openapi 파일을 만들어 내는 과정에서 multipart/form-data
요청과 관련된 처리를 지원하지 않고 있었기에 multipart/form-data
요청을 처리하지 못하고 있었던 것을 파악할 수 있었습니다.
조금 더 구체적으로는 요청 스펙을 정의하는 RequestModel
클래스가 multipart/form-data
를 처리하고 있지 않았습니다.
swagger.generator
는 multipart/form-data
요청을 처리할 수 있었습니다.
이에 저는 multipart/form-data
처리하는 방법으로 아래 두 가지 방법을 생각할 수 있었습니다.
restdocs-api-spec
의RequestModel
이multipart/form-data를
처리할 수 있도록 추가 구현을 진행한다.swagger.generator
가 생성하는swagger-spec.js
에 직접multipart/form-data
요청을 추가한다.
* 저는 swagger-spec.js
에 원하는 multipart/form-data
요청을 추가하는 방법을 선택하였지만 openapi 파일을 통해 swagger-spec.js
를 만들어내기 때문에 openapi 파일에 multipart/form-data
요청을 추가할 수도 있습니다.
swagger.generator가 만들어 내는 Swagger
swagger.generator
는 openapi 파일을 활용해 위 사진과 같은 결과물을 만들어 Swagger를 제공합니다.
해당 결과물을 파악하며 저는 index.html
에서는 swagger-spec.js
에서 정의한 스펙을 기반으로 Swagger를 제공하고 있음을 알 수 있었습니다.
이를 통해 swagger-spec.js
에 원하는 multipart/form-data
스펙을 직접 추가한다면 원하는 Swagger를 완성할 수 있을 것이란 생각을 할 수 있었습니다.
직접 multipart/form-data 요청을 추가하는 방법
저는 swagger.generator
가 제공하는 Swagger를 생성하는 테스크(generateSwaggerUI
)가 동작한 이후 multipart/form-data
요청을 추가하는 작업을 정의하였습니다.
tasks.register("generateApiSwaggerUI", Copy::class) {
dependsOn("generateSwaggerUI")
val generateSwaggerUISampleTask = tasks.named("generateSwaggerUI", GenerateSwaggerUI::class).get()
from(generateSwaggerUISampleTask.outputDir)
into("$projectDir/src/main/resources/static/docs/swagger-ui")
doLast {
// swagger-spec.js 위치 지정
val swaggerSpecSource = "$projectDir/src/main/resources/static/docs/swagger-ui/swagger-spec.js"
file(swaggerSpecSource).writeText(
// 원하는 위치에 MULTIPART/FORM-DATA_SPEC을 추가
file(swaggerSpecSource).readText().replace(
TARGET_SPEC,
TARGET_SPEC + MULTIPART/FORM-DATA_SPEC
)
)
}
}
val MULTIPART/FORM-DATA_SPEC = "" +
" \"requestBody\" : {\n" +
" \"content\" : {\n" +
" \"multipart/form-data\" : {\n" +
" \"schema\" : {\n" +
" \"type\" : \"object\",\n" +
" \"properties\" : {\n" +
" \"source\" : {\n" +
" \"type\" : \"string\",\n" +
" \"format\" : \"binary\"\n" +
" }\n" +
" }\n" +
"\n" +
" }\n" +
" }\n" +
" }\n" +
" },"
'개발' 카테고리의 다른 글
네임드 락을 활용한 동시성 제어 (2) | 2024.09.08 |
---|---|
Pinpoint 도입 이모저모 (0) | 2024.08.22 |
jOOQ 사용기 (1) | 2024.07.23 |
FEW MVP 기능을 구현하며 (0) | 2024.07.14 |
인터페이스가 필요한 순간 (0) | 2024.04.09 |