[Project] Spring multipart/form-data

조수훈·2023년 7월 27일
1

Project

목록 보기
3/8
post-thumbnail

본 포스팅은 스스로 공부한 내용을 정리하고 기록하기 위하여 올리는 내용이며, 잘못된 내용이 있을 수도 있음을 미리 밝힙니다. 잘못된 내용이 있거나, 더 좋은 방법이 있다면 댓글로 남겨주시기 바랍니다.


HTTP multipart/form-data

multipart/form-data 는 HTTP 프로토콜의 Content-Type 중 하나입니다. 말 그대로 multipart, 즉 요청 안에 여러개의 part가 있다는 뜻입니다.
모든 문자를 인코딩하지 않으며, 요청 안에 파일이나 이미지를 포함하여 서버로 전송할 때 주로 사용합니다.
각 파트의 헤더는 Content-Disposition 헤더를 포함하며, 필드 이름과 파일 이름 등의 정보를 포함합니다. 아래는 multipart/form-data 요청의 간단한 예제입니다.

POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=--------------------------1234567890

----------------------------1234567890
Content-Disposition: form-data; name="description"

John Doe
----------------------------1234567890
Content-Disposition: form-data; name="file"; filename="profile.jpg"
Content-Type: image/jpeg

[Binary data of the profile image]
----------------------------1234567890--

예시에서 하나의 multipart/form-date 요청안에 두개의 form-data 가 포함되는 것을 확인 할수 있습니다.
이렇게 구성된 multipart/form-data 요청은 클라이언트가 서버로 데이터를 전송할 때 사용되며, 서버는 이러한 요청을 해석하여 해당 데이터를 처리하거나 저장할 수 있습니다.

요청 코드

<form action="/upload" method="post" enctype="multipart/form-data">
 <input type="text" name="description"/>
 <input type="file" name="file"/>
 <button type="submit">전송</button>
</form>

@RequestPart

multipart/form-data 의 요청의 Part들을 파라미터와 연결하는 데 사용할 수 있는 어노테이션 입니다.

   @PostMapping("/upload")
    public String handleFileUpload(@RequestPart("file") MultipartFile file,
                                   @RequestPart("description") String description) {
        return "uploadSuccess";
    }

@RequestPart("file") MultipartFile file은 "file" 파트를 MultipartFile 객체로 처리합니다. 이것은 파일 업로드 필드에 해당하며 업로드된 파일의 내용을 나타냅니다.
@RequestPart("description") String description은 "description" 파트를 문자열로 처리합니다. 이것은 텍스트 필드에 해당하며 사용자가 입력한 설명을 나타냅니다.

@RequestParam

@RequestParam 또한 multipart/form-data 의 요청의 Part들을 파라미터와 연결하는 데 사용할 수 있는 어노테이션 입니다.
코드로 볼때 @RequestPart 와 @RequestParam 의 차이는 거의 없어 보입니다.

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file,
                                   @RequestParam("description") String description) {
        
        return "uploadSuccess";
    }

@RequestPart,@Requestparam 차이점

multipart/form-data 를 처리할때, @RequestParam 과 @RequestPart 의 주요 차이점은 다음과 같습니다.
파라미터가 String 또는 raw MultipartFile/Part 가 아닐때, @RequestParam 은 등록된 Converter 또는 PropertyEditor 를 통한 형식 변환에 의존하는 반면 @RequestPart는 요청 파트의 Content-Type 헤더를 고려하여 HttpMessageConverters에 의존합니다.
따라서 @ReuqestParam 은 기본 타입의 필드에 사용될 가능성이 높고, @RequestPart 는 JSON, XML 과 같이 더 복잡한 내용을 포함하는 파트에 사용될 가능성이 높습니다.

@ModelAttribute

컨트롤러에서 값을 받을때 어노테이션을 명시하지않으면 해당 어노테이션이 default로 설정됩니다. HTTP body 의 쿼리 파라미터 및 URL 쿼리 파라미터를 DTO객체를 통해 바인딩이 가능합니다. multipart/form-data 요청을 받게 되면, 모든 part의 파라미터를 받아올 DTO 객체에 매핑하게 됩니다.
그러나 @ModelAttribute 는 필드 내부와 1:1로 값이 constructor를 통해 매핑됩니다. 따라서 해당 DTO 의 필드에 접근할 수 있는 적절한 constructor가 존재하지 않는다면 값이 바인딩 될 수 없습니다.

  @PostMapping("/upload")
    public String handleFileUpload(@ModelAttribute FileUploadForm form) {
        MultipartFile file = form.getFile();
        String description = form.getDescription();
        return "uploadSuccess";
    }
    
  @Getter
  @AllArgsConstructor
  public class FileUploadForm {
      private MultipartFile file;
      private String description;
  }

@ReqeuestBody

application/json을 주고받을때 주로 사용하여, multipart/form-data요청을 받아야 하는 경우에는 사용이 불가합니다.

Reference

[multipart/form-data 설명]https://velog.io/@shin6403/HTTP-multipartform-data-%EB%9E%80

[Spring docs] https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestPart.html

profile
잊지 않기 위해 기록하기

0개의 댓글