DDD
DDD는 복잡한 도메인을 명확히 표현하고, 비즈니스 규칙을 코드 구조의 중심에 두는 설계 방식이다. 구성은 크게 Presentation → Application → Domain → Infrastructure 계층으로 나뉜다.
DDD의 중요 개념
- 도메인(Domain): 소프트웨어가 해결하려는 비즈니스 영역이나 문제 공간.
- 유비쿼터스 언어(Ubiquitous Language): 팀 내 모든 구성원이 공통으로 사용하는 언어로, 도메인 모델과 소통을 일관되게 유지.
- 바운디드 컨텍스트(Bounded Context): 도메인을 여러 개의 독립된 컨텍스트로 분리하여 복잡성을 관리.
- 애그리거트(Aggregate): 도메인 모델 내에서 일관성을 유지해야 하는 객체들의 집합.
- 루트 애그리거트(Root Aggregate): 애그리거트의 진입점이 되는 핵심 엔티티.
- 벨류 오브젝트(Value Object): 식별자가 필요 없는 객체로, 속성만으로 식별됨.
- 엔티티(Entity): 고유한 식별자를 가지며, 지속적인 생명주기를 가진 도메인 객체.
1. Presentation Layer (UI 계층)
역할
- 사용자의 입력을 받고 결과를 반환
- Application Service를 호출하여 처리 흐름을 시작함
구성 요소
Controller
- HTTP 요청/응답 처리
- DTO 매핑
- 비즈니스 로직 없음
DTO (Request / Response)
- 계층 간 데이터 전달 객체
- 검증 및 단순 변환만 수행
- 도메인 지식 포함 X
2. Application Layer (애플리케이션 계층)
역할
- 유즈케이스(Use Case) 실행
- 도메인 객체를 조립하고 트랜잭션 경계를 관리
- 도메인 규칙은 포함하지 않음 (흐름만 제어)
구성 요소
Application Service
- Controller → Application Service → Domain 객체 호출 흐름 구성
- 예: 주문 생성, 사용자 등록 프로세스 처리
Command / Query (옵션, CQRS 기반)
- Command: 상태 변경
- Query: 데이터 조회
3. Domain Layer (도메인 계층)
역할
DDD의 핵심. 비즈니스 규칙, 모델, 정책을 모두 포함하며 어떤 기술에도 의존하지 않아야 함.
구성 요소
Entity
- 고유 ID를 가지고 상태 + 행동을 가진 객체
- 예: Order, User
Value Object
- 식별자 없음, 속성 기반 비교
- 불변성 유지
- 예: Money, Address
Aggregate & Aggregate Root
- 불변성을 유지해야 하는 객체 그룹
- Root 외부에서는 내부 객체에 직접 접근 불가
Domain Service
- 특정 Entity에 속하지 않는 도메인 규칙 처리
- 무상태(stateless)
Repository Interface
- 도메인 계층에서 영속성 기술을 추상화한 인터페이스 선언
Domain Event
- 도메인 내 의미 있는 사건 표현 (예: 주문 생성됨)
4. Infrastructure Layer (인프라 계층)
역할
- 기술적 구현부 (DB, Network, File, 외부 API 등)
구성 요소
Repository 구현체
- Repository 인터페이스의 실제 구현
- 예: JPA 기반 구현
외부 API 연동
- RestTemplate, WebClient 등 호출
설정 / 구성 요소
- ORM 설정
- 메시지 브로커, Redis, Kafka 등
전체 구조 요약 (디렉토리 예시)
presentation/
└─ controller/
└─ dto/
application/
└─ service/
└─ command/
└─ query/
domain/
└─ entity/
└─ vo/
└─ service/
└─ repository/
└─ event/
└─ aggregate/
infrastructure/
└─ repository/
└─ external/
└─ config/DDD vs MVC 구조 비교
구조 차이 개요 표
| 구분 | MVC | DDD |
|---|---|---|
| 목적 | 빠른 개발, 화면 중심 | 도메인 복잡도 관리, 비즈니스 중심 |
| 주요 관심사 | UI 흐름 제어 | 도메인 모델링, 규칙 중심 |
| 계층 구성 | Model, View, Controller | Presentation, Application, Domain, Infrastructure |
| Model 역할 | DB 매핑 + 비즈니스 로직 혼재 | Domain Entity/VO/Service로 역할 분리 |
| 서비스 레이어 | 필수 아님 | Application Service + Domain Service로 명확 분리 |
| DTO 필요성 | 경우에 따라 생략 가능 | 필수적 (계층 간 책임 분리) |
| 일관성 | 상대적으로 느슨함 | Aggregate 중심 강한 일관성 |
DDD의 장점과 단점
장점
-
복잡한 도메인 표현에 강함
- 비즈니스 규칙이 코드 구조에 반영됨
- 유지보수 시 규칙 이해가 쉬움
-
변경에 강한 구조
- UI, DB 기술이 바뀌어도 Domain은 영향받지 않음
- 확장성 ↑
-
팀 간 협업 향상
- 도메인 언어(Ubiquitous Language)를 통해 동일 용어 사용 가능
-
테스트 용이
- Domain이 순수 로직만 담고 있기 때문에 단위 테스트 쉬움
단점
-
설계 비용이 높음
- 모델링 회의, Aggregate 설계, 이벤트 설계 등
- 소규모 프로젝트에는 과할 수 있음
-
학습 난이도
- DDD 개념(VO, Aggregate, Event 등)을 모두 이해해야 효과적
-
계층 분리로 초기 개발 속도 저하
- 파일/클래스 갯수 증가
- 단순 CRUD에서는 비효율적일 수 있음
MVC 대비 DDD를 선택해야 할 시점
DDD가 적합한 경우
- 도메인 규칙이 복잡하거나 자주 바뀜
- 금융, 결제, 유통, 정책 기반 시스템
- 장기 운영을 전제로 한 서비스
MVC 또는 단순 구조가 적합한 경우
- 단순 CRUD 위주의 시스템
- MVP 단계, 빠른 출시가 최우선
- 도메인 규칙이 거의 없음