용도부터가 다릅니다. Dto는 데이터 전달을 위한 View Layer에 속한 클래스로 변경 가능성이 다분하나, Entity는 DB Layer로 변경 가능성이 적은편에 속합니다. 이 둘을 구분짓지 않고 사용한다면, 전체 Layer에서 Entity에 대한 의존성이 높아져, 차후 수정사항에 대해 민접하게 대처하기 힘들어질 것입니다.
Controller에서 데이터를 전달할 때, Json 직렬화를 주로 사용합니다. 이때, Entity에 무분별한 Json 직렬화를 사용한다면 무한 참조 루프가 발생할 가능성이 높습니다. 또한 직렬화를 하며 Fetch Lazy한 필드까지 모두 참조한다는 것인데 이렇게 되면 Lazy Loading의 이점을 살릴 수가 없기도 합니다.
View Layer에서 데이터 전달을 담당하는 Dto는 Controller, DB Layer에 속해 비즈니스적 로직에 필요한 Entity는 Service에서 사용하는 것을 권장합니다. 그렇다면 Dto와 Entity간의 Mapping은 어디서 이뤄져야 할지 의문점이 생깁니다.
A Service Layer defines an application’s boundary [Cockburn PloP] and its set of available operations from the perspective of interfacing client layers. It encapsulates the application’s business logic, controlling transactions and coor-dinating responses in the implementation of its operations. - Martin Fowler
마틴 파울러는 Service Layer란 어플리케이션의 경계를 정의하고 비즈니스 로직 등 도메인을 캡슐화하는 역할이라고 정의합니다. 도메인 Model 즉, Entity를 표현 계층(Controller)에서 사용하는 경우 결합도가 증가하여, 도메인의 변경이 Controller의 변경을 촉발하는 유지보수의 문제로 이어질 수 있다는 것입니다.
이런 관점으로 볼 때, Layer간 데이터 전달 목적으로 DTO를 엄격하게 고수한다면 Entity와 Dto간의 Mapping이 이뤄지는 계층은 Service 레이어에서 정의되어야 한다는 의견이 존재합니다. 요청에 대한 응답 역시 Service 레이어의 일부분이기 때문입니다.
위와 같은 단점들이 Service에서 사용하게 되면 해결될 수 있습니다.
Entity와 Dto를 구분해야하는 이유와 어느 계층에서부터 구분할 것인지 알아봤지만, 다양한 의견들이 존재했습니다. Dto는 Layer 계층간 데이터 전달을 위한 객체이기에, Service까지 가져와 사용해도 된다는 의견과 여러 종류의 Controller에서 해당 서비스를 자유롭게 사용할 수 있도록 Dto는 Service까지 들어오는 것을 지양해야한다는 의견도 있었습니다.
답은 없는 것 같습니다. 심지어 이전에 다니던 회사에서는 Entity로 View단까지 사용했으니.
다만 개인적으로 Entity는 Controller까지 표출되지 않는게 낫다고 생각하며(본문의 내용과 같은 이유로), 현재 진행하고 있는 프로젝트에는 이와 같이 반영하려 합니다.
참고