Spring에서 Multipart File Upload와 JSON 처리: @RequestPart를 사용한 해결 방법
오늘 Spring Boot를 사용하여 파일 업로드를 처리하는 과정에서 여러 가지 문제를 겪었다.
특히, @RequestParam, @RequestBody, @RequestPart를 사용하여 파일 업로드를 시도했으나 예상치 못한 오류들이 발생했고, 이를 해결하기 위해 @RequestPart를 사용하여 문제를 해결하게 되었다.
이번 블로그에서는 이 문제를 해결하는 과정과 핵심적인 설정 및 코드 구현을 상세하게 설명하겠다.
Multipart File Upload와 JSON 데이터를 처리하는 방법을 배워보자.
Spring에서 파일 업로드와 JSON 데이터를 동시에 처리해야 하는 경우가 있다.
이때 @RequestBody와 @RequestPart의 적절한 사용법을 알지 못하면 여러 오류가 발생할 수 있다.
문제의 발생
나는 파일 업로드와 JSON 데이터를 동시에 처리해야 하는 상황에 직면했다.
사용자는 회원 가입을 할 때 MemberRegisterRequestDTO 객체와 함께 프로필 사진 파일을 업로드하려고 했다.
이를 위해 두 가지 데이터를 동시에 처리할 수 있도록 API를 작성하려고 했고, 그 과정에서 여러 오류가 발생했다.
오류 1: HttpMediaTypeNotSupportedException
HttpMediaTypeNotSupportedException
첫 번째로 마주친 오류는 HttpMediaTypeNotSupportedException이었다.
원인으로는 Spring에서 처리할 수 없는 Content-Type이 설정되어 있을 때 발생하는 오류이다.
Postman에서 요청을 보낼 때 Content-Type이 application/octet-stream으로 설정되었기 때문에,
Spring은 이를 처리하지 못하고 오류를 발생시켰다. 기본적으로 Spring은 multipart/form-data 형식을 기대하기 때문에 이 문제를 해결하기 위해서는 요청의 Content-Type을 multipart/form-data로 변경해야 한다.
나는 Content Type조차 설정하는 법을 몰랐기에, 여기서 또 엄청 해메었다.
나와같은 사람이 없기 위해서 이미지로 상세하게 설명하겠다.
대부분 블로그에서는 content-type을 application/json 으로 설정하면 끝나요 라고 너무 간단하게 말해준다.
우선 결과다.
위와 같이 content type을 설정해주면되는데 사실 저 창이 최신 postman에는 없다.
그때에는 가장 오른쪽의 점세개를 누르면, content type을 설정할 수 있게 필드가 생긴다.
이와같은 방법으로 Content-Type을 multipart/form-data로 변경할 수 있다.
오류 2: Cannot find @interface method 'consumes()
사실 consumes외에도 너무 다양한 오류를 맞았다.
java.lang.NullPointerException: Cannot invoke "org.springframework.web.multipart.MultipartFile.getOriginalFilename()" because "file" is null
@RequestParam, @RequestBody, @RequestPart를 계속 섞어가며 뭐가 맞나 계속 테스트를 끊임없이 진행했다(2시간 넘음..)
혼자 시도하다가 구글링한 결과,
두 번째 오류는 @RequestPart에서 consumes를 사용하려 했을 때 발생한 오류였다.
@RequestPart에 consumes = MediaType.APPLICATION_JSON_VALUE를 설정하려 했지만, consumes 속성은 @RequestPart에서 사용할 수 없다는 오류가 떴다.
이 오류는 @RequestPart가 MultipartFile과 함께 사용되기 때문에 JSON 데이터의 Content-Type을 따로 설정할 수 없다는 점에서 발생했다.
최종 문제 해결 과정: @RequestPart로 문제 해결
내가 선택한 해결책은 @RequestPart를 활용하는 것이었다.
Spring에서 @RequestPart는 Multipart 요청에서 파일과 JSON 데이터를 동시에 처리할 수 있도록 돕는다.
특히, 파일 업로드와 JSON 데이터를 동시에 처리할 때는 @RequestBody와 @RequestPart를 적절히 구분해야 한다.
다음은 내가 작성한 코드 예시다:
@PostMapping("/signup")
public ResponseEntity<MemberRegisterResponseDTO> signup(
@RequestHeader("Authorization") String authorizationHeader,
@RequestPart("request") MemberRegisterRequestDTO request, // JSON 데이터를 @RequestPart로 받음
@RequestPart("file") MultipartFile file, // 파일을 @RequestPart로 받음
HttpServletResponse response) {
log.info("회원가입 요청 시작");
MemberRegisterResponseDTO responseDTO = memberService.registerWithToken(authorizationHeader, request, response, file);
log.info("회원가입 요청 완료");
return ResponseEntity.ok(responseDTO);
}
포스트맨에 위에 알려준 Content-Type을 multipart/form-data만 잘 설정해주면 정상적으로 이미지와, request를 반환해줄것이다.
바로 해결하고싶은 분들을위한 트러블슈팅과 해결 사항 총정리
1. @RequestPart로 JSON 데이터와 파일을 동시에 받기
2. @RequestPart는 multipart/form-data 요청에서 데이터를 처리할 때 사용된다. 이 어노테이션은 파일뿐만 아니라 다른 데이터를 함께 전송할 수 있도록 돕는다. JSON 데이터를 request라는 이름의 파라미터로 받으려 @RequestPart("request")로 지정하고, 파일을 @RequestPart("file")로 처리하면 된다.
3. Postman에서 JSON과 파일을 동시에 보내기
Postman에서 요청을 보낼 때는 Body 탭을 열고 form-data를 선택한다. 이때 request 파트는 raw 형식으로 JSON 데이터를 입력하고, file 파트는 파일을 선택하여 전송한다.
Postman 설정 예시:
- key: request (JSON 데이터)
- value: JSON 데이터 (예: { "nickname": "minminmin", "birth": "1990-01-01", ... })
- key: file (업로드할 파일)
이 방식으로 JSON과 파일을 동시에 전송할 수 있다.
4. Content-Type 자동 설정
Postman은 form-data를 선택하면 Content-Type을 자동으로 multipart/form-data로 설정한다.
따라서 별도로 Content-Type을 수동으로 설정할 필요는 없다.
↑ 라고 대부분의 블로그에서 말하지만, 여기까지 찾아온 여러분은 저와 비슷하게 꼭 명시적으로 content-type을 수동으로 등록해주길 바란다.
결론
결과적으로, 나는 @RequestPart를 사용하여 파일과 JSON 데이터를 동시에 처리하는 문제를 해결했다.
Spring에서 파일 업로드와 JSON 데이터 처리는 multipart/form-data 방식으로 처리해야 하며, 이 방식을 사용해서 파일과 데이터를 동시에 받을 수 있었다. 또한, Postman에서 JSON 데이터를 raw 형식으로 보내고 파일을 form-data로 보내는 방법을 사용하면 이 문제를 쉽게 해결할 수 있다.(하지만 그렇다고해서 @RequestBody로 받고, @RequestParam 으로 섞어서 받으면 안된다.)
이번 에러를 통해서 Spring에서 파일 업로드와 JSON 데이터를 동시에 처리하는 방법을 배웠고, 특히 에러를 읽는 방법과 디버깅 방법에 대해서 깊은 공부를 해본것 같아 기분이 좋았다.
--- ft:
- 실제로 몇시간 동안 디버깅 엄청찍어보고,,, 에러코드 만 수십개.... ㅜㅠ
- 아래는 지인 총 동원해서 디코, 카카오로 하나하나 물어보고, 디버깅 과정도 배우고, 에러코드 읽는법을 다시 한번 체킹한날...
- 솔직히 코드는 너무 간단하고, 디버깅방법과 에러 대처법에 대한 고민을 많이해본것 같다.
'트러블 슈팅' 카테고리의 다른 글
깃 브랜치 네이밍 규칙 트러블슈팅: "슬래시 문제와 해결 방안" (0) | 2025.01.28 |
---|
댓글