트러블 슈팅

Spring에서 이미지, JSON 데이터 한번에 controller에서 클라이언트에 넘기기

min민 2025. 2. 7.

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-Typeapplication/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:

- 실제로 몇시간 동안 디버깅 엄청찍어보고,,, 에러코드 만 수십개.... ㅜㅠ 

- 아래는 지인 총 동원해서 디코, 카카오로 하나하나 물어보고, 디버깅 과정도 배우고, 에러코드 읽는법을 다시 한번 체킹한날...

 

 

- 솔직히 코드는 너무 간단하고, 디버깅방법과 에러 대처법에 대한 고민을 많이해본것 같다.

댓글