-
spring boot[Spring boot] 클라이언트의 전달 값을 바인딩시 사용되는@ModelAttribute와 @RequestBody의 차이점과 @ModelAttribute 바인딩 안되는 문제2025. 1. 5. 16:08728x90
public static class TestController { @PostMapping public ResponseEntity<String> modelTest(@ModelAttribute TestDTO testDTO) {} @PostMapping public ResponseEntity<String> bodyTest(@RequestBody TestDTO testDTO) {} }
RestAPI
를 개발하다 보면 JSON 형태의 요청을 많이 사용하게 되는데파일 요청을 위해선 form-data가 필요해서
form-data 요청으로 테스트 하던 중,
요청 파라미터가 정상적으로 바인딩 되지 않았습니다.
해결 방법은 찾았지만 그에 대한 내용을 정확하게 이해하기 위해
정리해보는 ModelAttribute와 RequestBody의 차이점!
@RequestBody
RequestBody는 Json(application/json) 형태의 body를 맵핑해주는 어노테이션입니다.
body 데이터는 Spring mvc의 HttpMessageConverter를 통해 객체로 변환되며,
setter를 이용하여 바인딩하는 형식이 아닌 객체의 기본 생성자를 통해 객체를 바인딩됩니다.
직렬화를 위해 기본 생성자가 필요하며 바인딩을 위한 필드명을 색인하기 위해선
getter/setter 중 한가지는 정의되어야 합니다.
@ModelAttribute
ModelAttribute는 일반 HTTP 요청이나 multipart/form-data 형태의 body를 맵핑해주는 어노테이션입니다.
어노테이션을 붙인 파라미터에 class 파일의 객체를 만들어 해당 클래스의 setter를 이용하여 요청 데이터를 바인딩합니다.
그렇기 때문에 바인딩할 class에 setter가 없으면 데이터가 정상적으로 바인딩 되지 않아서 데이터가 null이 됩니다.
코드에 @ModelAttribute를 작성하지 않더라도 ModelAttributeMethodProcessor를 통해 자동적으로 적용됩니다.
🔨 바인딩이 정상적으로 되지 않은 것에 대한 해결 방법
@ModelAttribute로 body 데이터를 바인딩 하는데 자꾸만 null 값이 세팅되어 이유를 찾아보니
바인딩 하려는 class에 어노테이션에 문제가 있다는 것을 알게됐습니다.
제가 만든 class에는 @NoArgsConstructor 와 @AllArgsConstructor 두개의 어노테이션이 작성되어 있는데
@Modelattribute는 생성자가 두 개 이상인 경우, 매개변수가 적은 생성자를 통해 객체를 생성 합니다.
그래서 기본 생성자를 선택해 객체를 초기화 하기 때문에 값이 바인딩 되지 않았습니다.
그래서 클래스 구성시 @NoArgsConstructor가 있으면 @Setter 어노테이션을 붙여주거나
@AllArgsConstructor 만을 작성해야 정상적으로 바인딩됩니다.
📚 Reference
https://tecoble.techcourse.co.kr/post/2021-05-11-requestbody-modelattribute/
728x90'spring boot' 카테고리의 다른 글
[Spring boot] mybatis join 테이블 jsp 출력하기 (0) 2023.10.21 [Spring Boot] ajax 요청시 404 뜰 때 (0) 2023.10.21 [Spring Boot] Maven 환경 Oracle 연동하기 (0) 2023.10.14 📙 [Error] Error resolving template [like/65/find], template might not exist or might not be accessible by any of the configured Template Resolvers ... (0) 2023.09.19 📙 [Error] No setter found for the keyProperty 'id' in ... (0) 2023.09.18