Multipart-Form에서 DTO가 중첩된 객체일 경우 Swagger가 convert 못 하는 문제

effiRin·2023년 2월 26일
0
post-thumbnail
  • 만약 request를 보낼 때 Json 형태의 DTO 뿐만 아니라 파일도 함께 보내고 싶다면 어떻게 해야할까?

Multipart-Form로 보내면 된다.
이때 주의할 점은 @RequestBody는 body에 있는 걸 Json으로 인식하기 때문에 @RequestPart를 붙여야 한다.

아니면 파일을 DTO 안에 넣어서 request를 보내도 된다.
즉 아래와 같은 구조의 DTO이다.

val name : String,
val age : Int, 
val file: FilePart

이 경우에도 swagger가 알아서 인식해서 파일과 DTO를 보내준다.



  • 하지만........ 만약 DTO가 중첩된 객체일 경우 문제가 발생한다.
    (DTO라는 객체 안에 또 다른 객체가 프로퍼티로 있는 경우)
val name : String,
val age : Int, 
val addressInfo: AddressInfo,
val file: FilePart

위와 같은 경우, **swagger가 AddressInfo라는 객체를 객체로 인식 못 하고 String으로 보내버린다.

Swagger-UI renders nested object as json input body instead of form-data.
스웨거 UI는 중첩된 객체를 폼데이터 대신에 json input body로 렌더링한다.)
https://github.com/swagger-api/swagger-ui/issues/7672

그래서 String을 AddressInfo 객체로 convert 할 수 없다는 오류가 발생한다.

cannot convert value of type 'java.lang.string' to required type dto
Spring 에러 - Failed to convert value of type 'spring.~.{VO명}' to required type 'java.lang.String'; nested exception is java.lang.IllegalStateException: Cannot convert value of type

저렇게 중첩된 객체일 경우엔 Application Json 형태로 보내야 인식을 한다.
하지만 Json으로 보내자니 DTO 안에는 첨부파일 file이 있다.
file은 multipart-form으로 보내야 하는데...


찾아보니까 postman일 경우엔 파일은 multipart-form으로,
다른 프로퍼티는 Json으로 선택해서 따로따로 보낼 수 있는 것 같다.

하지만 나처럼 백엔드이며 swagger를 쓰고 있는 사람이라면 저렇게 보낼 수 있는 방법은 없는 것 같다...ㅎ

1) 중첩된 하위 객체를 없애는 쪽으로 request DTO 구조를 바꾸거나
2) API를 분리해서 파일은 multipart-form으로, 중첩된 DTO는 json으로 따로 받는 식으로 바꾸거나
3) swagger 상에서는 확인을 못 하겠지만 저렇게 보내달라고 프론트분과 얘기를 해보거나...
기타 등등..

자신의 상황에 맞게 대안을 생각해야할 것 같다.
그래서 난 결국 API를 분리했다.


별 거 아닌데 꽤 고민하고 삽질했던 문제라서 적어본다.
추후에 좀더 공부하고 정리해보자.


[Spring] Json with MultipartFile
Object Mapping 어디까지 해봤니? : NHN Cloud Meetup
RequestBody and Multipart on Spring Boot / Blogs / Perficient
@RequestPart 사용할 때 주의사항. 그리고 @ModelAttribute

profile
모종삽에서 포크레인까지

0개의 댓글