여태까지 Request Dto를 만들면서,무지성으로 @Data, @AllArgsConstructor, @NoArgsConstructor를 사용해오곤 했다.
그런데 개인 프로젝트를 진행하다보니 front에서 데이터를 보내는 방식마다 어떻게 Dto에 값이 매핑되고 Repsonse되는지 몰라서 헤매게 되더라..(무지성 코딩의 폐해)
이 참에 Dto에서 어떻게 데이터가 바인딩되는지 알아보기로 했다!
보통 웹 request를 보낼 때, 어떻게 데이터를 보낼까?
크게 http parameter(?id=1&pwd=123
와 같은 쿼리스트링)으로 보내는 경우와,
http body 중 JSON 또는 form-data로 보내는 경우가 있다.
우리는 이렇게 request로 받은 데이터를 가공하거나 사용하기 위해서,
Dto클래스와 같이 Java 객체로 매핑하는 과정이 필요하다.
여기에서 request 데이터 → Java 객체(Dto)로 만드는 과정을 역직렬화라고 하고,
Java 객체(Dto) → response 데이터(Json)로 만드는 과정을 직렬화라고 한다.
Http Body의 Message를 읽기 위해서 스프링은 Http Message Converter에서 Jackson을 사용한다.
역직렬화(Json → Java객체)는 ObjectMapper를 사용하는데, Jackson Converter도 이와 같이 ObjectMapper를 사용한다.
ObjectMapper의 Dto 직렬화/역직렬화 과정은 다음과 같다.
(Dto클래스의 모든 필드의 접근제한자는 private/protected를 가정한다)
@Getter
public class RequestDto {
private String id;
private String pwd;
}
@Getter
@Setter 또는 @AllArgsConstructor
public class ResponseDto {
private String id;
private String pwd;
}
@AllArgsConstructor
를 사용해도 무방하다.Json타입이 아닌 데이터를 reuqest데이터로 받았다면 어떻게 할까?
쿼리스트링인 Http Parameter를 받거나,
form-data인 Http Body를 받는 경우, 우리는 @ModelAttribute
를 통해 Dto를 바인딩 할 수 있다.
@Getter
@Setter 또는 @AllArgsConstructor
public class RequestDto {
private String id;
private String pwd;
}
@ModelAttribute
는 setter나 모든생성자를 통해서 데이터를 바인딩한다.
따라서, getter만 있다면 객체의 값이 바인딩되지 않는다.
기본형 타입의 필드는 null이, 참조형 타입의 필드는 0와 같은 초기값이 바인딩된다.
나의 생각으로는 Json타입의 데이터의 경우 역직렬화와 직렬화 과정을 나누어 Repsonse할 필요가 있지만,
@ModelAttribute
의 경우 이 과정이 함께 일어나면서 데이터가 매핑됨과 동시에 바인딩하기 때문에 setter(또는 모든 생성자)의 선언이 필요한 것 같다.
@ModelAttribute
를 사용해 getter, setter(또는 모든생성자)를 통해 데이터를 바인딩할 수 있다.