API 구성을 하다보면, 보통 파일을 올리는 API가 따로 있고, json을 받는 API가 따로 있게 되긴 하는데, 같이 보낼 경우도 있다.
이럴 경우 content-type 가 multipart/form-data 로 들어 오게 된다.
이걸 다루기 이전에, 파일을 서버가 받는 방식부터 알아보면,
- multipart/form-data 로 받아서 MultipartFile 형으로 받는 방식이 있다
- base64 인코딩을 통해 json으로 받는다.
일반적으로 MultipartFile 을 통해 받는것이 선호된다. 그 이유는,
- 메세지의 용량이 json으로 주는것 보다 작다
- 사용하기 편리하다
- 디코딩 과정이 없으므로 속도 및 부하가 적어 대용량에서도 잘 쓰는 방식이다.
간단히 컨트롤러의 매핑된 메소드 예를 보면,
...
@PostMapping(value="/create")
public User createUser(@RequestPart UserCreateRequest request, @RequestPart(required = false) MultipartFile profileCreateRequest) {
return userService.create(request, Optional.ofNullable(profileCreateRequest));
}
...
이렇게 @RequestPart를 이용해서 MultipartFile 로 받는다.
일반 json과 파일형식을 multipart/form-data 로 받게 되면 위의 예 처럼 json 또한 @RequestPart 로 받아야 한다.
API에서 요청 인자값을 받는 몇가지 방식에 대해 알아보자.
- @RequestParam
- GET 요청에서, 파라메터 형식으로 받을때 (?id=xxxx)
- multipart/form-data 에서 일반 text로 받는 경우 사용
- 그러나 대부분은 dto를 이용하므로 이런경우는 잘 없음
- @RequestPart
- multipart/form-data 에서 json 이나 file 을 받을때 사용
- @PathVariable
- API 주소 뒤 /에 인자값이 추가된 경우.
@GetMapping("/users/{userId}")
public User getUser(@PathVariable("userId") String userId) {
// userId == "123"
return userService.findById(userId);
}
- PostMan 을 이용한 테스트
- 주로 포스트맨을 이용해서 API 통신 테스트를 하게된다

- Body -> form-data 를 선택
- Json 추가
- Key 에 이름을 입력(서버에서 받는 변수명과 일치하는게 좋음) -> 형식은 Text로 지정
- Value 에 json 문자열 자체를 입력
- Content-Type 에 application/json 을 명시 꼭 해야 함
- 이 항목이 없다면 우측에 있는 Bulk Edit 좌측 ... 눌러서 추가
- 파일 추가
- Key 에 이름 입력(서버에서 받는 변수명과 일치하는게 좋음) -> 형식은 File 로 지정
- Value 에서 보낼 파일을 선택
Swagger의 문제점 -> 서버 코드 수정
위의 방식대로 하면 포스트맨에선 아무 문제 없다. 다만, Swagger에서는 문제가 생긴다. Swagger 에서는 application/json 과 multipart/form-data 를 같이 쓸 수가 없다. 따라서 json 문자열과 파일을 같이 보내면
Content-Type 'application/octet-stream' is not supported 오류가 발생하게 된다.
이를 해결하기 위한 방법으론,
1. json 을 "파일" 로 보낸다
- json 내용을 파일로 작성하여, 파일을 추가 후 보낸다.
2. json을 text로 보낸 후 서버 내부에서 파싱한다
2번 방식으로 접근하면, 포스트맨에서도, swagger 에서도 모두 동작한다. 다만 HttpMessageConverter 가 json을 DTO 클래스로 Deserialize를 할 수 없으므로, 컨트롤러 코드 내부에서 수동으로 작업을 해주어야 한다.
...
@PostMapping(value="/create")
public User createUser(@RequestPart String request, @RequestPart(required = false) MultipartFile profileCreateRequest) {
//아래의 코드를 사용하여 수동으로 Deserialize를 해야 한다.
DTO클래스명 변수명 = new ObjectMapper().readValue(request, DTO클래스명.class);
return userService.create(변수명, Optional.ofNullable(profileCreateRequest));
}
...
이때, 포스트맨에서는 json 문자열을 전송할때, Content-type 설정을 기존 application/json 에서 application/text 로 변경한다
'Backend > SpringBoot' 카테고리의 다른 글
| REST -> RESTful 예제 (0) | 2025.09.19 |
|---|---|
| Interceptor 이용하여 요청 확인하기 (0) | 2025.09.18 |
| 클라이언트의 파일을 받아 처리하기 (0) | 2025.09.15 |
| @RequestBody, @ResponseBody (0) | 2025.09.15 |
| 상태코드 반환. @ResponseStatus, ResponseEntity (0) | 2025.09.15 |