@RequestBody 와 @ModelAttribute의 차이점

채상엽·2022년 5월 11일
0

Spring

목록 보기
6/21
post-custom-banner

@RequestBody 와 @ModelAttribute 차이점

@RequestBody

클라이언트가 보내는 HTTP 요청 본문(Json, xml 등)을 Java 오브젝트로 변환한다. HTTP 요청 본문 데이터는 Spring에서 제공하는 HttpMessageConverter를 통해 타입에 맞는 객체로 변환된다.

@RequestBody로 받는 DTO는 기본생성자만 있다면, setter가 없더라도 값이 잘 들어감을 확인할 수 있다. 어떻게 이게 가능할까?

위에서 HttpMessageConverter를 이용해 타입에 맞는 객체로 변한다고 했는데, 이중에서 MappingJackson2HttpMessageConverter를 사용한다. 이를 내부적으로 타고 들어가보면, ObjectMappper 클래스를 통해 Json 값을 Java 객체로 역직렬화함을 확인할 수 있다.

역직렬화란 ? : 생성자를 거치지 않고 리플렉션을 통해 객체를 구성하는 메커니즘

직렬화가 가능한 클래스들은 기본 생성자가 필수이기 떄문에, 기본 생성자가 정의되어 있지 않으면 데이터 바인딩에 실패한다.

그렇다면 ObjectMapper에서는 Json에 명시된 key를 Java 객체의 필드명과 어떻게 매핑시킬까?

  • getter나 setter 메서드의 접두사(get, set)을 지운다.
  • 문자의 첫 문자를 소문자로 변환한 문자열을 참조하여 필드명을 알아낸다.

그렇기 때문에 만약 @RequestBody에 매핑되는 DTO 객체에 getter나 setter가 없다면 테스트 실행시 HttpMessageNotWritableException 예외가 발생한다.

정리

  • 본문의 Json, xml, text 등의 데이터가 HttpMessageConverter를 통해 파싱되어 Java 객체로 변환된다.
  • @ResquestBody를 사용할 객체는 필드를 바인딩할 생성자나 setter 메서드가 필요없다.
    • 단, 직렬화를 위한 기본 생성자는 필수다.
    • 데이터 바인딩을 위한 필드를 알아내기 위해 getter나 setter중 한 가지는 정의가 되어야한다.

@ModelAttribute

클라이언트가 보내는 HTTP 파라미터들을 Java 오브젝트에 바인딩(매핑)하는 것이다. 주로 쿼리 스트링이나 요청 본문에 삽입되는 form 형태의 데이터를 처리한다.

필드에 접근해 데이터를 바인딩할 수 있는 생성자를 삭제하고 바인딩을 시도하면 바인딩이 실패한다. 단 생성자가 없어도 setter가 있다면 바인딩이 성공한다.

+)
스프링에서 객체의 타입에 어노테이션을 생략하면 default로 @ModelAttribute가 적용된다.

정리

  • @ModelAttribute는 HTTP 파라미터 데이터를 Java 객체에 매핑한다.
    • 따라서 데이터를 바인딩할 수 있는 생성자 또는 setter가 필요하다.
  • Query String 또는 Form 형식이 아닌 데이터는 처리할 수 없다.
profile
프로게이머 연습생 출신 주니어 서버 개발자 채상엽입니다.
post-custom-banner

0개의 댓글