@ModelAttribute를 통해 body에 값을담아 전송 할 때, 값이 들어가지 않고 null이 들어가는 문제를 직면했습니다.
클라이언트로부터 받은 요청을 객체로 바인딩 하는 경우는 @RequestParam, @RequestBody, @ModelAttribute 세 가지가 있습니다.
각각의 방식과 특징과 차이를 알아 보려고 합니다.
@RequestParam은 각각의 HTTP 요청 파라미터를 받아오기 위해 사용됩니다. 따라서 위 세가지 방식 중에 @RequestParam만 Body를 직접 조회하지 않습니다.
@ResponseBody
@PostMapping("test/request-param")
public TestData requestParam(@RequestParam String name,
@RequestParam int age) {
TestData testData = new TestData();
testData.setName(name);
testData.setAge(age);
return testData;
}
위 코드를 기반으로 postman을 통해 @RequestParam을 전송해 보았습니다.
@RequestParam 전송
@RequestParam 반환
파라미터를 받아서 Json 형태로 name과 age가 응답되었습니다.
@RequestBody는 클라이언트가 전송하는 JSON(application/json) 형태의 HTTP Body 내용을 Java Object로 변환시켜주는 역할을 합니다. 가장 큰 특징은 바인딩이 아닌 변환을 시키는 것이기 때문에 변수들의 Setter 함수가 없어도 정상적으로 저장됩니다. 또한 기본 생성자를 통해 변환을 하기 때문에 기본 생성자를 만드는 것이 필요합니다.
@ResponseBody
@PostMapping("/test/request-body")
public TestData requestBody(@RequestBody TestData testData) {
return testData;
}
@RequestBody 전송
@RequestBody 반환
@RequestBody 역시 Json 형태로 응답이 되었습니다.
@RequestBody에 대한 자세한 내용
@ModelAttribute을 통해 body에 값을 담아 전송
@ModelAttribute을 통해 body 반환
name에 null이 들어오고 age도 디폴트 값 0이 들어왔다. 이 부분이 @RequestBody와의 차이점이다.
요청을 보낼 떄 Content-Type을 multipart/form-data 형태로 바꾸면
다음과 같이 잘 들어간다.
@ReuqestBody는 위에 말했듯이 기본 생성자를 통해 객체를 생성해서 내부적으로 Reflection을 통해 값을 넣어주지만 @ModelAttribute는 값을 변환시키는 것이 아니라 바인딩하는 방식이다. 즉 setter를 통해 일대일 객체 바인딩을 하는 것이다.
클라이언트가 보내는 파라미터가 1개일 경우 @RequestParam으로 하는 편이 좋지만, 파라미터가 여러개가 될 경우 객체로 바인딩하기 위해 @ModelAttribute를 사용 하는 것이 좋다는 느낌을 받게 되었다.
@RequestParam 은 @RequestParam은 HTTP 요청 파라미터를 받기 위해서 사용된다.
@RequestBody 은 Spring은 메시지를 변환하는 과정에서 객체의 기본 생성자를 통해 객체를 생성하고 내부적으로 Reflection을 사용해 값을 할당
@ModelAttribute 은 변환이 아닌 바인딩을 시키기 때문에 변수들의 Setter 함수가 없으면 저장되지 않는다. 또한 @ModelAttribute를 사용하여 HTTP Body에 내용을 담기 위해서는 multipart/form-data 형식으로 전송해야 한다.
참고자료
https://amagrammer91.tistory.com/106
https://galid1.tistory.com/769