팀 프로젝트를 시작하기 앞서 회의 중 MSA구조를 프로젝트에 적용하기 위해선 DDD패턴도 같이 언급되었다.
간단하게 프로젝트의 구조를 그려봤는데, DTO의 위치가 애매해서 튜터님께 물어본 후 말씀을 토대로 알아보았다.
presentation 계층? application 계층?
presentation 계층에 위치한 DTO

application 계층에 위치한 DTO

- DDD패턴에서 DTO의 위치는 중요한 설계 결정이다.
DTO는 일반적으로 데이터를 위한 객체로, 비즈니스 로직을 포함하지 않고 주로 application 계층과 외부 시스템 간의 데이터 교환을 위해 사용된다.
Presentation 계층에서의 사용
정의
- Presentation 계층은 사용자 인터페이스(UI)나 API를 담당한다.
클라이언트와 서버 간의 데이터 교환을 담당하며, 보통 controller가 이 계층에 속한다.
DTO 사용 시점
- Client로 데이터를 전송할 때, presentation 계층에서 DTO를 사용하여 도메인 모델과 별개로 데이터를 구조화할 수 있다.
장점
-
UI 및 외부 시스템에 맞는 데이터 형식을 제공할 수 있다.
예를 들어, 프론트엔드에서 필요한 형식에 맞게 데이터를 변환하고 전달할 수 있다.
-
도메인 모델을 외부에 그대로 전달하지 않기 때문에, 도메인 로직과 UI/Client 간의 결합도를 줄일 수 있다.
단점
- 중복이 생길 수 있다.
예를 들어, application 계층에서도 DTO 를 사용한다면 presentation 계층과 application 계층에 동일한 형태의 DTO가 중복될 수 있다.
- presentation 계층에서 너무 많은 로직을 처리하게 되어 책임이 불분명해질 수 있다.
Application 계층에서의 사용
정의
- Application 계층은 비즈니스 로직을 처리하는 domain 계층과 presentation 계층 사이에서 중재 역할을 하는 계층이다.
이 계층은 주로 서비스와 애플리케이션 로직을 포함하며, 도메인 객체의 변환과 외부 시스템과의 인터페이스를 담당한다.
DTO 사용 시점
- Application 계층에서 도메인 모델을 Client 나 외부 시스템에 전달하기 전에 DTO 로 변환하여 전달한다.
애플리케이션 서비스에서 도메인 모델을 전달하고자 할 때, DTO 를 사용하여 비즈니스 로직과의 분리를 유지한다.
장점
- 도메인 계층의 보호
- 도메인 모델을 외부와 직접 연결하지 않고, DTO 를 통해 데이터를 전송함으로써 도메인 모델의 캡슐화를 유지한다.
- 서비스 간 데이터 전달이 더 깔끔하고 명확하게 이루어질 수 있다.
- 변환 로직을 Application 계층에 두면, Presentation 계층은 오직 사용자 인터페이스 관련 로직만 담당하고, Application 계층은 비즈니스 로직과 데이터 전달을 담당할 수 있어 책임 분리가 잘 이루어진다.
단점
- 복잡성 증가
- Application 계층에서 DTO 와 도메인 모델 간의 변환 로직을 관리해야 하므로, 복잡도가 증가할 수 있다.
그래서 어디에 둬야 해?
Presentation
- 주로 UI 로직이 복잡하고 프론트엔드와 데이터 계약이 독립적일 때 사용된다.
예를 들어, 프론트엔드에서 필요한 데이터 구조가 도메인 모델과 완전히 다를 때 유용
- API 디자인이 중요한 경우, REST API 또는 GraphQL API 에서 Client 와의 데이터 계약을 명확히 정의하고, Client 와의 데이터 전송을 관리하는데 적합하다.
Application
- 비즈니스 로직과 관련된 데이터를 외부 시스템에 전달할 때 사용한다.
Application 계층에서 데이터 변환, 비즈니스 로직 실행, 외부 시스템과의 데이터 전달을 한 곳에서 처리할 수 있다.
- 서비스의 책임 분리가 중요할 때, 도메인 로직과 UI 로직을 분리하고자 할 때 유리
요약
Presentation
- UI와 API 요청/응답을 위한 데이터 변환이 필요한 경우
- 클라이언트와의 데이터 계약이 중요한 경우 (예: REST API, GraphQL)
- 도메인 모델을 직접 노출하지 않고 캡슐화할 때
Application
- 서비스 계층에서 도메인 객체와 클라이언트 간 변환을 수행할 때
- 비즈니스 로직이 포함된 데이터 변환이 필요할 때
- 내부 서비스 간 데이터 전달을 캡슐화하고 API 의존성을 줄일 때