마이크로서비스로 개발하는 강의를 보는데 DTO를 Mapper해서 사용했다.
나도 전에는 Service 계층에서 DTO를 Entity로 변환해서 사용하였는데 어떤 계층에서 변환을 하는 것이 좋을지, DTO를 왜 사용하는지 다시 정리해보고자 한다.
DTO = Data Transfer Object
즉, 데이터를 전송하는 객체
벨덩에서는 "They are flat data structures that contain no business logic"이라고 정의했다.
또한 메서드 호출 수를 줄이기 위해 프로세스 간에 데이터를 전달하는 개체이다.
DTO는 원격 호출 수를 줄이는 데 도움이 되므로 원격 호출이 있는 시스템에서 유용하다.
즉, 필요한 모든 데이터를 그룹화하고 API와의 상호작용을 최적화하는 단일 요청으로 서버에 보낸다.
DTO를 어디까지 사용하고 어디에서 변환할지가 중요한 것이 아니라 도메일 모델 보호가 핵심이라는 것!!!
그러나
https://www.inflearn.com/questions/53023
책이나 강의를 보면서 만드는 프로젝트는 대부분 이 방법을 사용했었다.
또한 마틴 파울러는 서비스 레이어에서 DTO로 변환하는것을 제시한다.
https://martinfowler.com/eaaCatalog/serviceLayer.html
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.
이러한 의견도 있다고 한다!!
서비스 레이어에는 DTO가 아닌 도메인을 받아야 여러 컨트롤러에서 해당 서비스를 사용할 수 있다.
하지만, 실무에서는 보통 여러 종류의 컨트롤러에서 한 서비스를 사용하기보다는 한 종류의 컨트롤러에서 서비스를 사용하기에 엄격하게 DTO의 진입을 막을 필요는 없다고 한다.
서비스 요청, 응답 시 서비스 계층의 메서드가 사용하는 서비스 DTO를 별도로 만들고, DTO와 서비스 DTO를 매핑하는 Mapper를 끼워넣는 방법이 있다고 한다.
Mapper를 사용하면 RequestDTO가 변경되더라도 ServiceRequest 객체는 변하지 않기 때문에 Mapper만 수정해주면 서비스 계층에는 아무런 영향을 미치지 않는다는 것이다.
즉, 매퍼가 중간다리 역할을 해주면서 컨트롤러와 서비스 계층이 완전히 분리되는 효과를 얻을 수 있다.
https://techblog.woowahan.com/2711/
서비스 계층에서 DTO를 그대로 파라미터로 받아 내부에서 엔티티로 변환하는 방법을 기본으로 사용하다가 프로젝트 규모가 커지고 컨트롤러와 서비스 계층의 분리, 모듈화가 필요하다고 느낄 때 Mapper와 서비스 DTO를 만들어 3번으로 넘어가는 것이 좋을 것 같다.
프로젝트 규모에 따라 유동적으로 선택하자.
정해진 답은 없으며 해당 상황에 맞는 적절한 선택지를 가져가는 것이 중요하다.
참고 링크들에 보면 이런 결론이 나와있다.
추가> 핵심 비즈니스 로직을 가지고 있는 서비스 로직과, 화면에 맞춘 읽기 전용 서비스 로직을 별도로 분리해서 설계하는 것이 중요!
https://www.baeldung.com/java-dto-pattern
벨덩의 DTO Pattern에서 Common mistakes에 관한 내용이 있다.
참고
https://sedangdang.tistory.com/296
https://catsbi.oopy.io/ecfb5269-a531-4687-b41f-55f80c90acea