이번 포스트는 간단한 회고입니다.
예전 개발을 막 시작할 응애응애 개발자일 코생아 당시 파일(이미지 포함)을 REST API로 주고 받는 기능을 구현해야 할 때가 있었습니다.
아무것도 몰라서 무지성 DTO, 무지성 @RequestBody를 남발할 때 였죠.
당시 경험을 그대로 가져왔습니다.
첨부파일을 어떻게 보내야 할지 모르겠다구요? @RequestBody 밖에 모르신다구요?
환영합니다.
때는 바야흐로 열심히 첨부파일 관련 API를 구현하던 중 문득 API 끼리 첨부파일을 주고 받을 때는 어떻게 해야하지?
라는 순수한 궁금증이 생겼습니다.
항상 JSON 형식의 데이터만 주고 받았기 때문에, @ResponseBody 를 통해 JSON 데이터를 자바 객체로 변환하여 사용해 왔습니다.
누구나 느끼겠지만, 이미지를 포함한 파일을 JSON 형식으로 주고 받는 것은 뭔가 부자연스럽다고 생각했습니다.
검색해본 결과 미디어 파일의 경우 multipart/form-data 형식으로 받아서, 다른 변환이 필요했습니다!
바로 @ResponseBody가 아닌 @RequestPart를 사용해야 했는데요.
사용법을 알아보겠습니다.
@RequestPart는 HTTP request body에 multipart/form-data 가 포함되어 있는 경우에 사용하는 어노테이션입니다.
제 상황과 같이 MultipartFile이 포함되어 있는 경우 해당 어노테이션을 사용하게되면
MultipartResolver가 동작하여 역직렬화를 하게 됩니다.
만약 MultipartFile이 포함되어있지 않다면, @RequestBody
와 마찬가지로 동작하게 됩니다.
함께 사용하는 옵션으론 여러가지가 있습니다.
required = true
로 설정한 후 미디어 파일을 요청하지 않는다면 예외가 발생합니다.끄덕끄덕 이해한뒤 바로 적용해 보았습니다
//controller
@PostMapping("/user")
public void getUser(@RequestBody UserRequestDto dto, @RequestPart(value="file", required=false) MultipartFile file){
//
...
}
처음엔 위와 같은 방법으로 기존의 받던 JSON 데이터의 경우는 그대로 @ResponseBody 를 사용하고,
미디어 파일의 경우만 @RequestPart 를 적용해주었습니다.
내 자신을 칭찬하며 실행해본 결과,, 에러가 떴는데요
POST한 데이터가 잘 도착하지 않고 계속 알 수 없는 예외만 보여주고 있는 상황이었습니다.
무엇이 문제였을까요?
알고보니 기존의 JSON 데이터를 @RequestBody이 아닌 마찬가지로 @RequestPart를 적용해주어야 했습니다.
다만 주의할 점은 JSON 데이터의 경우 MediaType을 반드시 application/json 으로 지정해주어야 합니다.
위의 코드를 정정해본다면 아래와 같습니다.
//controller
@PostMapping("/user")
public void getUser(@RequestPart(value="request") UserRequestDto dto, @RequestPart(value="file", required=false) MultipartFile file){
//
...
}
원할한 예시를 위해 포스트맨 요청 예시도 보겠습니다.
기존 JSON 데이터를 form-data의 텍스트 형식으로 작성한 후 MediaType을 application/json 으로 지정해준 걸 볼 수 있습니다.
실행 결과 요청이 정상적으로 잘 전달 되었습니다.
References