[Spring] @RequestBody, @ModelAttribute, @RequestParam, @RequestPart 차이

Damongsanga·2024년 4월 20일
post-thumbnail

오늘 모 부트캠프 2차 과제테스트를 보았는데.. 어이없는 부분에서 시간을 너무 쏟는 바람에 결국 완성하지 못하고 말았다. 컨트롤러 단에서 파라미터로 넘어온 값을 제대로 받지 못한 원인을 파악하지 못한 것이다. 이런 기본적인것도 제대로 해결하지 못했다는데에 많이 속상했고, 오늘 공부한 내용을 바로 글로 남기려 한다.

기존 프로젝트에서는 데이터를 모두 application/json 형태로 보내다보니 당연히 @RequestBody 형태로 데이터를 받았다보니, 테스트 케이스에서 multipart/form-data 형태로 들어오는 값의 파라미터가 모두 null로 받아와지는 것을 늦게 파악하고 말았다.

이에 HTTP 요청의 데이터를 받는 4가지 방법에 대해 정리해보겠다.


@RequestBody

  • 내부 동작

    • MappingJackson2HttpMessageConverter 사용
    • 생성자와 Setter 없이도 가능 (물론 기본생성자는 필요)
    • ObjectMapper를 사용해 JSON 값을 Java 객체로 역직렬화
    • 역직렬화 : 생성자를 거치지 않고 리플렉션을 사용해 객체를 구성
    • 직렬화 가능한 클래스는 기본 생성자가 필수로 필요
    • ObjectMapper에 의해 데이터 바인딩을 위한 필드 명을 알아내기 위해 getter나 setter 중 1개는 필요
  • 사용 경우

    • 주로 Ajax 요청 (application/json)에서 사용
    • 주로 JSON, XML, 기타 데이터 형식의 요청 처리시 사용
    • 클라이언트 단에서 요청 시 반드시 Content-Type을 명시해줘야함
    • binary 파일을 포함하고 있지 않은 데이터를 받는 역할
      • 따라서 multipart 요청은 불가
      • multipart/form-data: 파일 업로드시 사용되며 '파일을 비롯한 여러 데이터가 있음'이라는 뜻을 가짐. (@RequestBody로 받을 수 없음 !!)

@ModelAttribute

  • 내부 동작

    • HTTP 요청의 “파라미터”를 객체로 바인딩
    • ajax에서 사용하려면 데이터를 parameter로 넘겨주면 된다
    • @ModelAttribute는 Form 형식의 HTTP 요청 본문 데이터만을 인식해 맵핑
  • 사용 경우

    • Content-type이 multipart/form-data의 형태를 받을때
    • HTTP 파라미터를 받는 경우
    • 주로 HTML 폼 데이터를 처리할 때 사용
  • JSON 형태의 데이터를 전송하면 415 Error 발생

  • @ModelAttribute는 필드 내부와 1:1로 값이 Setter나 Constructor를 통해 매핑

    • 따라서 값에 직접 접근할 수 있는 생성자가 있거나 기본생성자 + Setter 조합이 필요

@RequestParam

  • 사용 경우

    • 하나의 파라미터만 받을 때 사용
    • @RequestParam 또한 @RequestPart와 같이 MultipartFile을 받을 때 사용가능
      • 파라미터가 String이나 MultipartFile이 아닌 경우 Converter나 PropertyEditor에 의해 처리
  • 내부 동작

    • 기본적으로는 파라미터가 필수로 받도록 설정되어있어 required=false를 설정해줘야할지 고민해야
  • 많은 데이터를 하나의 파라미터로 받는 것은 유지 보수성의 측면에서 좋지 않음

    • 많은 데이터를 주고받는 경우에는 @RequestBody와 DTO를 이용하는 편이 좋다.

@RequestPart

  • 사용 경우
    • @RequestBody가 필요하지만 Binary Stream이 포함되는 경우(MultipartFile과 같은)에 사용
  • 내부 동작
    • MultipartFile이 포함되는 경우에 MultipartResolver가 동작하여 역직렬화
    • MultipartFile이 포함되지 않는 경우엔 @ReqeustBody 같이 HttpMessageConverter가 동작

요약

  • @RequestBody

    • content-type이 application/json 형태 요청에 사용. multipart/form-data 요청에 사용 불가
    • 생성자와 Setter 없이도 가능
  • @ModelAttribute

    • Content-type이 multipart/form-data의 형태를 받을때 사용 가능
    • 값에 직접 접근할 수 있는 생성자나 기본생성자 + setter가 필요
  • @RequestParam

    • 한개의 파라미터만 받을 때 사용
    • 기본 설정은 반드시 값을 받아야함으로, 만약 값이 들어오지 않을 수도 있다면 required=false를 설정
  • @RequestPart

    • Binary Stream이 포함되는 경우(MultipartFile과 같은)에 사용

+) multipart/form-data 요청 처리를 위한 applicaiton.yml 설정

  • 파일 업로드 시 파일 크기 제한, 요청 전체 크기 제한 등의 옵션 제어 필요
spring:
  servlet:
    multipart:
      max-file-size: 2MB
      max-request-size: 10MB
      file-size-threshold: 0

참고자료

https://tecoble.techcourse.co.kr/post/2021-05-11-requestbody-modelattribute/
https://devhooney.tistory.com/179
https://middleearth.tistory.com/35

profile
향유하는 개발자

0개의 댓글