[Spring] @RequestPart를 활용하여 JSON + MultipartFile 동시 전송하기 (Feat. 게시판에서 게시물 생성과 첨부 파일 업로드 한번에 처리하기)

2025. 2. 13. 10:11·BackEnd/Spring & JPA
목차
  1. 1. 시작하며
  2. 2. @RequestBody와 @RequestPart 비교
  3. 2.1 @RequestBody란?
  4. 1) @RequestBody의 특징
  5. 2.2 @RequestPart란?
  6. 1) @RequestPart의 특징
  7. 3. JSON + 파일 전송 시 문제점
  8. 3.1 @RequestBody의 한계
  9. 4. @RequestPart를 활용한 JSON + MultipartFile 전송
  10. 4.1 백엔드에서 JSON + MultipartFile 데이터 요청 받아 처리하기
  11. 4.2 프론트엔드에서 multipart/form-data 요청 보내기
  12. 4.3 @RequestPart와 consumes 속성의 관계
  13. 1) consumes 속성이란?
  14. 2) consumes 속성에 지정할 수 있는 미디어 타입 (MIME 타입)
  15. 3) multipart/form-data 요청에서 JSON을 받을 수 있는 이유 (@RequestPart에서MediaType.APPLICATION_JSON_VALUE을 consumes에 추가할 필요가 없는 이유)
  16. 5. @RequestBody vs @RequestPart 비교
  17. 6. 결론
  18. 7. 참고

1. 시작하며

웹 애플리케이션을 개발할 때, JSON 데이터와 파일을 함께 전송해야 하는 경우가 있습니다.

예를 들어, 게시글 작성 시 게시글 정보(JSON)와 첨부파일(MultipartFile)을 함께 API에 전달해야 하는 경우를 생각해 볼 수 있습니다.

보통 API에서 @RequestBody를 사용하여 JSON 데이터를 받지만, multipart/form-data 요청에서는 @RequestBody를 사용할 수 없습니다.

이러한 경우, Spring의 @RequestPart 어노테이션을 활용하면 JSON과 파일을 동시에 전송할 수 있습니다.

이 글에서는

  1. @RequestBody와 @RequestPart의 차이점
  2. @RequestPart를 활용하여 게시글 정보(JSON) + 첨부파일을 한 번의 요청으로 처리하는 방법
  3. 프론트엔드에서 multipart/form-data로 API를 호출하는 방법

위 내용을 정리하고 실전 예제 코드를 통해 이해를 돕겠습니다.

2. @RequestBody와 @RequestPart 비교

2.1 @RequestBody란?

@RequestBody는 HTTP 요청 본문(body) 데이터를 자바 객체로 변환하는 역할을 합니다.

Spring에서는 HttpMessageConverter를 이용하여 요청 데이터를 처리하며, 일반적으로 application/json 타입의 데이터를 처리합니다.

1) @RequestBody의 특징

  • application/json 타입의 요청 데이터를 받아 자바 객체로 변환
  • 파일을 포함한 multipart/form-data 요청을 처리할 수 없음
  • @RequestBody를 사용할 경우 Content-Type을 반드시 명시해야 함 (application/json)
  • 단순 JSON 형식의 요청 데이터를 DTO로 변환하여 사용할 때 주로 활용
  • API에서 클라이언트가 보낸 JSON 데이터를 검증하고 비즈니스 로직에서 활용할 때 유용

즉, 파일을 포함하여 데이터를 전송해야 하는 경우에는 @RequestBody를 사용할 수 없으며, JSON 데이터를 DTO로 변환하여 처리할 때 적합합니다.

2.2 @RequestPart란?

@RequestPart는 multipart/form-data 요청을 처리할 때 사용됩니다.

@RequestPart를 사용하면 파일과 JSON 데이터를 함께 전송할 수 있습니다.

1) @RequestPart의 특징

  • JSON 데이터 + 파일을 함께 처리 가능
  • Content-Type이 multipart/form-data여야 함
  • MultipartFile을 함께 받을 수 있음
  • @RequestBody와 다르게 JSON과 파일을 함께 전송할 수 있도록 지원

3. JSON + 파일 전송 시 문제점

3.1 @RequestBody의 한계

@PostMapping("/boards")
public ResponseEntity<Long> createBoard(
    @RequestBody BoardCreateRequest boardCreateRequest // JSON 데이터 받기
) {
    long boardId = boardUseCase.createBoard(boardCreateRequest);
    return ResponseEntity.ok(boardId);
}

위와 같이 @RequestBody를 사용하면, JSON 데이터는 받을 수 있지만 파일은 받을 수 없습니다. (즉, 게시글 생성 정보만 받을 수 있습니다.)

이는 @RequestBody가 application/json 형식의 데이터만 처리하도록 동작하기 때문입니다.

multipart/form-data 요청에서는 @RequestBody를 사용할 수 없으므로, 다른 방법이 필요합니다.

4. @RequestPart를 활용한 JSON + MultipartFile 전송

4.1 백엔드에서 JSON + MultipartFile 데이터 요청 받아 처리하기

  • @RequestPart를 사용한 Spring 컨트롤러 예제 코드
@PostMapping(
    value = "/boards",
    consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public ResponseEntity<Long> createBoardWithFiles(
    @RequestPart("board") BoardCreateRequest boardCreateRequest, // JSON 데이터 받기
    @RequestPart(value = "files", required = false) List<MultipartFile> files // 파일 받기 (선택적)
) {
    long boardId = boardUseCase.createBoardWithFiles(boardCreateRequest, files);
    return ResponseEntity.ok(boardId);
}

해당 코드에서 @RequestPart 동작 방식은 다음과 같습니다.

  • @RequestPart("board") → JSON 데이터(BoardCreateRequest)를 multipart/form-data에서 추출하여 역직렬화
  • @RequestPart(value = "files", required = false) → MultipartFile 리스트를 받아 파일을 처리
  • consumes = MediaType.MULTIPART_FORM_DATA_VALUE → multipart 요청을 처리하도록 설정

이제 API 요청 시 JSON 데이터와 파일을 동시에 전송할 수 있습니다.

4.2 프론트엔드에서 multipart/form-data 요청 보내기

  • FormData를 활용하여 JSON과 파일을 함께 전송하는 React 예제 코드
function createBoardWithFiles(request: BoardCreateRequest, files?: File[]) {
  const formData = new FormData();

  // JSON 데이터 추가 (Blob으로 변환)
  const jsonData = new Blob([JSON.stringify(request)], { type: 'application/json' });
  formData.append('board', jsonData);

  // 파일 추가
  if (files && files.length > 0) {
    files.forEach(file => {
      formData.append('files', file);
    });
  }

  // API 호출
  return api.post('/boards', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
  });
}

해당 코드의 요청 흐름은 다음과 같습니다.

  • JSON 데이터를 Blob으로 변환하여 FormData에 추가
  • files 배열을 formData.append('files', file)을 통해 추가
  • multipart/form-data 형식으로 API에 전송

이제 프론트엔드에서 게시글 데이터 + 파일을 함께 서버로 전송할 수 있습니다.

4.3 @RequestPart와 consumes 속성의 관계

Spring에서는 @RequestPart를 활용하여 JSON 데이터와 파일을 함께 처리할 수 있습니다.

이때, @PostMapping 또는 @RequestMapping의 consumes 속성을 적절히 설정하는 것이 중요합니다.

1) consumes 속성이란?

consumes 속성은 해당 API가 처리할 수 있는 요청의 Content-Type을 명시하는 역할을 합니다.

즉, 클라이언트가 전송하는 요청의 MIME 타입이 consumes 속성에 지정된 값과 일치해야 합니다.

Spring에서 사용할 수 있는 consumes 속성에는 여러 미디어 타입이 있으며, 대표적인 예는 다음과 같습니다.

2) consumes 속성에 지정할 수 있는 미디어 타입 (MIME 타입)

MIME 타입 설명
MediaType.APPLICATION_JSON_VALUE (application/json) JSON 데이터 처리
MediaType.APPLICATION_XML_VALUE (application/xml) XML 데이터 처리
MediaType.APPLICATION_FORM_URLENCODED_VALUE (application/x-www-form-urlencoded) URL 인코딩된 폼 데이터 처리 (HTML 폼 제출 시 사용)
MediaType.MULTIPART_FORM_DATA_VALUE (multipart/form-data) 파일 업로드 처리 (JSON + 파일 전송 가능)
MediaType.ALL_VALUE (*/*) 모든 콘텐츠 타입 허용

3) multipart/form-data 요청에서 JSON을 받을 수 있는 이유 (@RequestPart에서MediaType.APPLICATION_JSON_VALUE을 consumes에 추가할 필요가 없는 이유)

multipart/form-data 요청을 처리할 때는 JSON 데이터가 multipart의 일부(part)로 포함되기 때문에 별도로 application/json을 consumes에 명시할 필요가 없습니다.

즉, MediaType.MULTIPART_FORM_DATA_VALUE만 지정하면 JSON 데이터도 함께 처리할 수 있습니다. Spring이 multipart 내부의 JSON을 자동 변환하여 처리해 주기 때문입니다.

5. @RequestBody vs @RequestPart 비교

어노테이션 사용 목적 지원하는 Content-Type JSON + 파일 동시 전송 가능 여부
@RequestBody JSON 요청 본문을 객체로 변환 application/json ❌ (파일 포함 불가)
@RequestPart multipart/form-data 내 JSON 및 파일 처리 multipart/form-data ✅ (파일 포함 가능)

6. 결론

  • @RequestBody는 application/json 요청만 처리 가능하며, 파일을 함께 전송할 수 없음
  • @RequestPart를 사용하면 JSON + 파일을 동시에 전송 가능
  • 프론트엔드에서는 FormData를 활용하여 JSON을 Blob으로 변환 후 전송

이번 글에서는 Spring에서 @RequestPart를 활용하여 JSON과 파일을 동시에 처리하는 방법을 정리했습니다.

@RequestPart를 사용하면 게시글과 첨부파일을 하나의 API 요청으로 처리할 수 있어 데이터 정합성을 보장할 수 있습니다.

REST API 설계 시, 리소스 중심의 URL을 유지하고, HTTP 메서드를 적절히 사용하여 multipart/form-data 요청을 처리하는 것이 중요합니다.

또한, 프론트엔드에서는 FormData를 활용하여 JSON을 Blob으로 변환하는 방식도 고려해야 합니다.

위와 같은 방법으로 설계를 변경하는 것이 바람직합니다. 이번 문제 해결 과정을 통해 HTTP 표준 준수와 RESTful 설계의 중요성을 다시 한 번 깨달을 수 있었습니다.

7. 참고

  • spring boot @RequestBody랑 @RequestPart를 같이 파라미터로 받으면 Request…
  • Multipart :: Spring Framework
  • @RequestBody :: Spring Framework

'BackEnd > Spring & JPA' 카테고리의 다른 글

[Spring Cloud MSA] Config, Gateway, Eureka까지 MSA 핵심 구조 쉽게 이해하기  (1) 2025.04.15
[Spring Boot] MySQL Master/Slave 복제 설정과 Read/Write 자동 분기 처리 방법 정리  (0) 2025.03.24
[Spring Data JPA] JPA 엔티티 설계 시 생성자 접근 제한을 PROTECTED로 설정하는 이유  (0) 2025.01.21
[Spring] @ResponseBody VS ResponseEntity<T>  (0) 2025.01.06
[Spring] @Controller VS @RestController  (0) 2025.01.06
  1. 1. 시작하며
  2. 2. @RequestBody와 @RequestPart 비교
  3. 2.1 @RequestBody란?
  4. 1) @RequestBody의 특징
  5. 2.2 @RequestPart란?
  6. 1) @RequestPart의 특징
  7. 3. JSON + 파일 전송 시 문제점
  8. 3.1 @RequestBody의 한계
  9. 4. @RequestPart를 활용한 JSON + MultipartFile 전송
  10. 4.1 백엔드에서 JSON + MultipartFile 데이터 요청 받아 처리하기
  11. 4.2 프론트엔드에서 multipart/form-data 요청 보내기
  12. 4.3 @RequestPart와 consumes 속성의 관계
  13. 1) consumes 속성이란?
  14. 2) consumes 속성에 지정할 수 있는 미디어 타입 (MIME 타입)
  15. 3) multipart/form-data 요청에서 JSON을 받을 수 있는 이유 (@RequestPart에서MediaType.APPLICATION_JSON_VALUE을 consumes에 추가할 필요가 없는 이유)
  16. 5. @RequestBody vs @RequestPart 비교
  17. 6. 결론
  18. 7. 참고
'BackEnd/Spring & JPA' 카테고리의 다른 글
  • [Spring Cloud MSA] Config, Gateway, Eureka까지 MSA 핵심 구조 쉽게 이해하기
  • [Spring Boot] MySQL Master/Slave 복제 설정과 Read/Write 자동 분기 처리 방법 정리
  • [Spring Data JPA] JPA 엔티티 설계 시 생성자 접근 제한을 PROTECTED로 설정하는 이유
  • [Spring] @ResponseBody VS ResponseEntity<T>
개발자 동긔
개발자 동긔
배우고 느낀점들을 기록합니다. 열정 넘치는 백엔드 개발자로 남고싶습니다.
  • 개발자 동긔
    Donker Dev
    개발자 동긔
  • 전체
    오늘
    어제
    • Category (39)
      • BackEnd (23)
        • JAVA (15)
        • Spring & JPA (7)
      • Database (4)
      • Computer Science (2)
        • Network (0)
        • Security (0)
        • Web (1)
      • DevOps (6)
        • Docker (1)
        • Jenkins (0)
        • Monitoring (2)
        • CICD (1)
      • 트러블 슈팅 (3)
      • 성능 개선 (1)
      • Project (0)
  • 인기 글

  • 태그

    java
    restful api 설계
    Jenkins
    JPA
    nginx
    spring cloud msa
    와일드카드
    SSH
    @RequestBody
    mysql master/slave replication
    interface
    docker
    master/slave db 이중화 처리
    restful api
    인터페이스
    Database
    spring boot
    CICD
    Spring
    docker compose
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
개발자 동긔
[Spring] @RequestPart를 활용하여 JSON + MultipartFile 동시 전송하기 (Feat. 게시판에서 게시물 생성과 첨부 파일 업로드 한번에 처리하기)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.