Spring Boot에서는 MultipartFile
형식을 사용하여 파일을 input으로 받을 수 있다. 이 때, 다수의 입력 변수 및 Multipart 파일을 함께
처리해야 할 경우 @ModelAttribute
를 사용하여 API 요청에 필요한 여러 입력 변수와 파일을 한 번에 처리할 수 있었다 💫
해당 과정을 제품 등록 시 이미지와 여러 제품의 상세 정보를 입력하는 API를 예로 들어 다루고자 한다
@ModelAttribute
를 사용하지 않을 경우@PostMapping(consumes = { "multipart/form-data" })
public ResponseEntity<Object> create(
@RequestParam String param1,
@RequestParam int param2,
@RequestParam MultipartFile file
) {
...
}
위와 같이 multipart File 외 다른 input의 수만큼 @RequestParam
을 생성하고, MultipartFile을 추가로 input으로 지정해주어야 한다.
input의 개수가 많지 않을 때는 괜찮지만, input의 수가 많아지면 가독성이 떨어진다
@PostMapping(consumes = { "multipart/form-data" })
public ResponseEntity<Object> create(
@RequestBody YourInputDto input,
@RequestParam MultipartFile file
) {
...
}
@RequestBody
는 HTTP 요청의 본문(body)를 객체로 매핑하는데 사용되지만, MultiupartFile
은 multipart/form-data 요청의 다른 부분(part)에 위치한 파일 데이터를 읽어오기 위해 사용되기에 함께 처리할 수 없다multipart/form-data 요청의 예시
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=boundary123
--boundary123
Content-Disposition: form-data; name="text_field" // part 1
This is a text field
--boundary123
Content-Disposition: form-data; name="file"; filename="example.txt" // part 2
Content-Type: text/plain
Contents of the file.
--boundary123--
@PostMapping(consumes = { "multipart/form-data" })
public ResponseEntity<Object> create(
@ModelAttribute @Valid ProductInput productInput,
Errors errors
) {
...
}
public class ProductInput {
@NotBlank(message = "제품 명은 반드시 있어야 합니다")
@Pattern(
regexp = "^.{5,29}$",
message = "제품 명은 5자 이상 30자 미만이어야 합니다."
)
@Schema(example = "아오리사과")
private String name;
// many other inputs
private MultipartFile img;
...
}
@ModelAttribute란?
: 클라이언트에서 전송된 요청 데이터를 자바 객체에 바인딩 할 때 사용되는 스프링 어노테이션
제품의 이미지를 파일로 받아오도록 변경함으로써 프로젝트의 첫 issue를 해결할 수 있었다 🫣