본문 바로가기
회고

💥 Spring Boot에서 JSON + 이미지 업로드 시 @RequestPart, @ModelAttribute 삽질기

by 창따오 2025. 7. 27.
728x90

😵 배경

회원가입 기능을 만들면서 다음 조건을 만족해야 했다:

  • JSON 형식으로 유저 정보 (nickname, email, address 등) 전송
  • 이미지 파일도 같이 업로드
  • DTO 안에 AddressDto처럼 중첩 객체가 포함된 구조

처음엔 단순하게 생각했다.

@PostMapping("/signup")
public ResponseEntity<?> signup(@RequestBody SignUpRequest request) { ... }

그런데 이미지까지 같이 업로드하려면 @RequestBody는 더 이상 사용할 수 없고,
multipart/form-data 방식으로 받아야 한다.

 


🧪 1차 시도: @RequestPart

@PostMapping(value = "/signup", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> signup(
    @RequestPart("request") SignUpRequest request,
    @RequestPart(value = "image", required = false) MultipartFile image
) { ... }

📌 Postman 설정도 다음과 같이 했다:


 

Key Type Value

 

request Text JSON 문자열
image File (프로필 이미지)

✅ 여기까지는 좋았지만...

❌ 에러 발생:

이후에도 다음과 같은 삽질들이 이어짐:

  • DTO 내부에 record 타입을 써서 Jackson 파싱 실패
  • 내부 클래스에 static 안 붙여서 Jackson 인스턴스 생성 실패
  • Postman에서 “스마트 따옴표” 사용해서 파싱 에러 발생
  • Jackson이 내부 중첩 객체를 파싱하지 못해서 null로 남음

😤 2차 시도: @ModelAttribute로 변경

차라리 단순하게 form-data 기반으로 처리하자.

✅ 컨트롤러 변경:

@PostMapping(value = "/signup", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> signup(@ModelAttribute SignUpRequest request) {
    ...
}

 

✅ DTO 구조 변경:

@Getter
@Setter
@NoArgsConstructor
public class SignUpRequest {
    private String nickname;
    private String email;
    private String name;
    private String password;
    private String phoneNumber;
    private AddressDto address = new AddressDto(); // 핵심
    private MultipartFile image;

    @Getter
    @Setter
    @NoArgsConstructor
    public static class AddressDto {
        private String city;
        private String street;
        private String zipcode;
    }
}

✅ Postman 설정:


 

nickname Text changddao
email Text test@naver.com
address.city Text Seoul
image File 프로필 이미지
 

✔️ 내부 필드는 address.city처럼 점(.) 표기법으로 처리 가능

 

🧠 배운 점

 

@RequestPart JSON 파싱은 Jackson에 맡겨야 하며, 내부 클래스 static, 기본 생성자 필요
@ModelAttribute Setter 기반 바인딩, 내부 객체는 미리 초기화하거나 Setter 필수
Multipart + JSON 현실적으로 @ModelAttribute 방식이 가장 직관적
Postman 사용 Text로 JSON 보낼 땐 반드시 "따옴표" 주의
DTO 구조 record ❌, class + getter/setter + no-args ✅

✅ 마무리

이 삽질만 정리해도 이후에 어떤 Multipart 상황이 와도 두렵지 않다.
같은 문제로 고생하는 분들에게 이 글이 도움이 되길 바라며...