『도메인 주도 개발 시작하기 - DDD 핵심 개념 정리부터 구현까지』를 읽고 정리한 내용입니다.
네 개의 영역
애플리케이션은 크게 표현, 응용, 도메인, 인프라 네 개의 영역으로 구성된다.
사용자
│
▼
표현(UI)
│
▼
응용(Application)
│
▼
도메인(Domain)
│
▼
인프라(Infrastructure)
표현(UI) 영역
표현 영역은 사용자의 요청을 받아 응용 영역에 전달하고, 처리 결과를 사용자에게 반환하는 역할을 담당한다.
주요 책임은 다음과 같다.
- 사용자 요청을 수신한다.
- HTTP 요청 데이터를
Request DTO(Command)로 변환한다. - 응용 계층의 서비스를 호출한다.
- 응용 계층에서 반환한 결과를
Response DTO로 변환한다. - 변환된 결과를 HTTP 응답으로 반환한다.
HTTP Request
│
▼
Controller
│
▼
Request DTO(Command)
│
▼
Application Service
------------------------
Application Service
│
▼
Response DTO
│
▼
JSON
│
▼
HTTP Response
응용 (Application) 영역
응용 영역은 사용자의 요청에 해당하는 유스케이스를 구현하는 영역이다.
주요 책임은 다음과 같다.
- 유스케이스를 구현한다.
- 트랜잭션을 관리한다.
- 필요한 도메인 객체를 생성하거나 조회한다.
- 실제 비즈니스 로직은 도메인 객체에 위임한다.
즉, 응용 영역은 전체적인 작업의 흐름을 제어하고, 구체적인 비즈니스 규칙은 도메인 영역에서 처리하도록 한다.
도메인 (Domain) 영역
도메인 영역은 애플리케이션의 핵심 비즈니스 로직을 구현하는 영역이다.
도메인 모델을 관리하며, Entity, Value Object, Aggregate, Repository, Domain Service 등의 구성 요소를 포함한다.
인프라(Infrastructure) 영역
인프라 영역은 애플리케이션을 구현하는 데 필요한 기술적인 기능을 담당하는 영역이다.
대표적으로 다음과 같은 기능이 해당한다.
- 데이터베이스
- Redis
- Kafka
- 외부 API
- 메시지 큐
- 파일 저장소
즉, 인프라 영역은 도메인과 응용 영역이 비즈니스 로직에 집중할 수 있도록 기술적인 구현을 담당한다.
계층 구조 아키텍처
계층 구조 아키텍처에서는 각 계층이 자신의 역할을 수행하며, 상위 계층이 하위 계층에 의존하는 구조를 갖는다.
표현
│
▼
응용
│
▼
도메인
│
▼
인프라
특징
계층 구조 아키텍처의 기본적인 특징은 다음과 같다.
- 상위 계층은 하위 계층에 의존한다.
- 하위 계층은 상위 계층을 알지 못한다.
- 각 계층은 자신의 역할에 집중한다.
이러한 구조를 통해 각 계층의 책임을 분리할 수 있다.
문제점
하지만 계층 구조를 단순하게 적용하면 응용이나 도메인 계층이 인프라 계층의 구체적인 구현체에 직접 의존하는 문제가 발생할 수 있다.
예를 들어 다음과 같은 구조이다.
OrderService
│
▼
JpaOrderRepository
OrderService가 JpaOrderRepository에 직접 의존하면 다음과 같은 문제가 발생한다.
- JPA에서 다른 기술로 변경할 때 영향을 받는다.
- 구현 기술에 대한 의존성이 증가한다.
- 테스트가 어려워질 수 있다.
이러한 문제를 해결하기 위해 DIP(Dependency Inversion Principle)를 적용할 수 있다.
DIP (Dependency Inversion Principle)
DIP는 고수준 모듈이 저수준 모듈의 구체적인 구현에 의존하지 않고, 추상화에 의존하도록 만드는 원칙이다.
즉, OrderService가 JpaOrderRepository와 같은 구체적인 구현체를 직접 의존하는 것이 아니라 OrderRepository라는 인터페이스에 의존하도록 만든다.
DIP 적용 전
OrderService
│
▼
JpaOrderRepository
OrderService가 특정 구현 기술에 직접 의존하고 있는 구조이다.
DIP 적용 후
OrderRepository
(Interface)
▲
│
┌───────────────┴───────────────┐
│ │
│ implements │ implements
▼ ▼
JpaOrderRepository MongoOrderRepository
▲ ▲
└───────────────┬───────────────┘
│
OrderService
OrderService는 OrderRepository라는 추상화에 의존한다.
실제 구현은 JpaOrderRepository나 MongoOrderRepository가 담당한다.
이 구조에서는 저장 기술이 변경되더라도 OrderService는 OrderRepository 인터페이스만 알고 있기 때문에 변경의 영향을 적게 받는다.
장점
DIP를 적용하면 다음과 같은 장점이 있다.
- 구현체를 쉽게 변경할 수 있다.
- 테스트가 쉬워진다.
- 고수준 모듈과 저수준 모듈의 결합도가 낮아진다.
- 구현 기술이 변경되어도 비즈니스 로직에 미치는 영향을 줄일 수 있다.
도메인 영역의 주요 구성 요소
도메인 영역은 비즈니스 개념을 객체로 표현하며, 대표적인 구성 요소로 Entity, Value Object, Aggregate, Repository, Domain Service가 있다.
| 구성 요소 | 설명 |
|---|---|
| Entity | 고유한 식별자를 갖는 객체이다. 도메인의 고유한 개념을 표현하며 데이터와 비즈니스 로직을 함께 관리한다. |
| Value Object | 고유한 식별자를 갖지 않는 객체이다. 주로 개념적인 값을 표현하기 위해 사용한다. |
| Aggregate | 관련된 Entity와 Value Object를 하나의 단위로 묶어 관리한다. |
| Repository | Aggregate의 영속성을 관리하는 역할을 담당한다. |
| Domain Service | 특정 Entity에 속하지 않는 도메인 로직을 담당한다. |
각 구성 요소는 서로 다른 책임을 가지며, 이를 적절하게 분리하는 것이 도메인 모델을 구성하는 데 중요하다.
요청 처리 흐름
앞에서 살펴본 각 영역은 사용자의 요청을 처리하는 과정에서 서로 협력한다.
사용자의 요청은 표현 영역에서 수신하고, 응용 영역으로 전달된다. 응용 영역은 유스케이스를 수행하면서 필요한 도메인 객체를 사용하고, 도메인 영역에 비즈니스 로직을 위임한다.
도메인 객체가 데이터를 저장하거나 조회해야 하는 경우에는 Repository를 사용하며, 실제 데이터베이스 접근과 같은 구체적인 구현은 인프라 영역에서 담당한다.
전체적인 요청 처리 흐름은 다음과 같이 표현할 수 있다

.
결국 네 개의 영역은 각자의 책임을 분리하면서도 하나의 요청을 처리하기 위해 협력한다. 특히 도메인 영역에 핵심 비즈니스 로직을 위치시키고, 인프라와 같은 기술적인 구현에 대한 의존성을 낮추는 것이 DDD 아키텍처에서 중요하다.