본문 바로가기
개발/Spring

@RequsestBody와 Setter

by 설이주인 2023. 9. 18.

DTO에서 Setter을 사용하는 부분에 대해서 확인 중에 신기한 부분을 발견해서 정리해본다.

 

https://jojoldu.tistory.com/407

 

@Request Body에서는 Setter가 필요없다?

회사에서 근무하던중 새로오신 신입 개발자분이 저에게 하나의 질문을 했습니다. POST 요청시에 Setter가 필요없는것 같다고. 여태 제가 알던것과는 달라서 어떻게 된 일인지 궁금했습니다. 정말 P

jojoldu.tistory.com

@RequestBody는 Setter가 필요없다?

주로 RequestBody로 받는 파라미터는 @Data와 함께 사용한다. 근데 Setter가 필요 없다?

 

몇가지 실험을 해보자

 

1. 조합 : RequestBody, Data

@ResponseBody
@PostMapping("/else")
public  String testClose(@RequestBody testVo vo, Model model) throws Exception {
    return "else";
}

@Data
public class testVo {
  private String testName;
}

 

2. 조합 : RequestBody, Getter, NoArgsConstructor

@ResponseBody
@PostMapping("/else")
public  String testClose(@RequestBody testVo vo, Model model) throws Exception {
    return "else";
}

@Getter
@NoArgsConstructor
public class testVo {
  private String testName;
}

 

3. 조합 : RequestBody, Getter (기본 생성자 없이)

@ResponseBody
@PostMapping("/else")
public String testClose(@RequestBody testVo vo) throws Exception {
    return "else";
}

@Getter
public class testVo {
  private String testName;
}

실패를 예상했는데…?

 

이럴때는 하나하나 보는게 답이다..

 

@RequestBody

Annotation indicating a method parameter should be bound to the body of the web request. The body of the request is passed through an [HttpMessageConverter]to resolve the method argument depending on the content type of the request. Optionally, automatic validation can be applied by annotating the argument with @Valid.

 

HttpMessageConverter (Spring Framework 6.0.12 API)

Read an object of the given type from the given input message, and returns it.

docs.spring.io

doc의 설명을 확인하면 requestbody는 httpMessageConverter의 도움을 받아서 타입에 따른 값을 setting 하는거 같다.

그럼 RequestBody가 어떻게 set을 진행하는지 따라가보자..

 

타고타고 들어가보면 AbstractJackson2HttpMessageConverter에서 readInternal > readJavaType으로 진행 되는거 같다.

readJava안에의 메인 포인트는 ObjectMapper라고 생각한다.

코드를 쭈우우욱 따라가보면 오브젝트매퍼와 역직렬화를 통해서

_valueInstantiator.createUsingDefault와 setCurrentValue를 통해서 값을 셋팅한다.

이후

converter과 readWithMessageConverter > resolveArgument를 거친 이후 Controller에 안착한다.

 

이렇게 값이 전부 다 자동 셋팅이 되는가?

값을 Setter 없이 @RequestMapping으로만 가져오기 위해서는 PostMapping으로 진행해야한다.

GetMapping으로는 안된다.

 

이는 Post와 Get의 data setting 방식이 다르기 때문인데.. post는 objectmapper가 값을 전환해주는 방식이기에 다능한 것이지만

get의 경우에는 wWebDataBinder의 initBeanPropertyAccess()안에서 사용되는 JavaBean 방식으로 진행하기에 Setter 없이는 어렵다.

 


 

PostMapping + RequestBody 조합이 setter가 필요 없는것은 맞지만.. DTO로  데이터 이동을 진행할때 가끔 해당 DTO 안에 있는 값을 가공할 일이 존재하기에 @Data를 작성하는 방향으로 진행할꺼 같다.