주특기 심화주차에 들어서 백엔드 팀과제를 진행하면서 기술 매니저님이 "DTO에 @Getter가 필요한 이유가 뭐에요?"라고 물어보셨는데, 지금까지 의식적으로 DTO에는 당연히 @Getter 써야지 라고만 생각했던 터라 질문에 대답을 할 수가 없었다.
그래서 이 글을 통해 그 이유에 대해 정리해보려고 한다.
DTO(Data Transfer Object)란?
DTO는 데이터를 Transfer(이동)하기 위한 객체이다.
Client가 Controller에 요청을 보낼 때도 RequestDto의 형식으로 데이터가 이동하고, Controller가 Client에게 응답을 보낼 때도 ResponseDto의 형태로 데이터를 보내게 된다.
Controller와 Service, Repository 계층간 데이터 교환도 DTO의 형태로 이동하게 된다.
View에서 Controller로 넘어오는 데이터를 담거나, Controller에서 Service로 넘기는 데이터를 담거나 할 때 사용할 수 있다.
DTO는 그저 계층간 데이터 교환이 이루어 질 수 있도록 하는 객체로, 특별한 로직을 가지지 않는 순수한 데이터 객체이다.
DTO는 단순히 데이터를 옮기는 용도이기 때문에 굳이 Setter를 이용해 값을 수정할 필요가 없이, 생성자만을 사용하여 값을 할당한다.
Spring에서 Controller계층과 Service계층 사이의 데이터 전송을 위해 DTO를 사용하는데, 클라이언트 요청에 포함된 데이터를 전송받을때 RequestDto라는 이름을 쓰고 서버의 응답에 관한 데이터를 전송하는데 ResponseDto라는 이름으로 주로 DTO를 사용한다.
RequestDto의 데이터를 Service단에서 사용하기 위해 getter 메소드를 사용하는 일은 빈번하다.
그래서 Service 클래스에서 getter 메소드를 사용할 때 DTO클래스에 @Getter가 없으면 컴파일러 체크 예외가 발생하기 때문에 @Getter 체크가 가능하다.
그러나 ResponseDto는 데이터 반환을 위해 사용하기 때문에 데이터를 초기화하는 작업은 있지만 getter 메소드로 외부 클래스에서 불러오는 경우는 없을 수 있다
그래서 ResponseDto 클래스에는 @Getter를 붙여주지 않아도 컴파일러 체크 예외가 발생하지 않을 수 있고, 실제로 서버도 작동한다.
그러나 @Getter가 없는 DTO를 사용하는 로직을 수행할 때 아래와 같은 예외가 발생한다.
No serializer found for class '소스파일경로' and no properties discovered to create BeanSerializer
요청에 따른 응답을 반환할 때 DTO 객체를 다른 데이터 형식으로 변환시켜줘야 하는데, Spring은 Jackson 라이브러리를 사용하여 Json 데이터들을 직렬화 / 역직렬화 작업을 진행한다. (DTO <-> Json)
이처럼 Spring에서 개발자 대신 데이터 변환을 해주기 위해 ResponseDto의 데이터 호출하게 되고, 이를 위해 getter 메소드가 필요하다.
추가적으로 대부분의 필드는 private로 사용하여 접근을 막는다.
그래서 외부에서 사용하기 위해서는 getter가 필요하다.