현재 배달앱 커머스를 개발 중인데 layered architecture로 구현했다가 비즈니스 로직이 서비스에 집중돼서 테스트 코드 및 유지보수가 너무 어렵다..
그래서 DDD패턴으로 바꿔보고자 한다.
Domain-Driven-Design
특정 도메인 모델이 유효하게 적용되는 명확한 경계.
가령, 배달 앱에서의 고객(Customer) 이라는 단어가 쓰이더라도 각 비즈니스(Context)마다 고객이 의미하는 바와 필요한 데이터가 다르다. 주문 컨텍스트에서 고객은 무슨 메뉴를 장바구니에 담았고 결제는 어떻게 했는지가 중요한 주체이다. 하지만 배달 컨텍스트에서는 고객의 결제 수단이나 메뉴는 중요하지 않다. 여기서의 고객은 오직 음식을 받은 도착치 좌표와 수령시 요청사항으로 정의된다.
'여기서부터 여기까지는 이 단어를 이런 의미로만 쓴다'라고 선을 긋는 작업이 Bounded Context이다.
┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
│ • Controller, DTO (Request/Response) │
│ • 사용자 입력 검증, 응답 변환 │
└─────────────────────────────────────────────────────────────┘
│ depends on
▼
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ • Application Service (유스케이스 조율) │
│ • Command/Query Service (CQRS) │
│ • 트랜잭션 관리, 이벤트 발행 │
└─────────────────────────────────────────────────────────────┘
│ depends on
▼
┌─────────────────────────────────────────────────────────────┐
│ Domain Layer (핵심) │
│ • Entity, Value Object, Aggregate │
│ • Domain Service, Domain Event │
│ • Repository Interface │
│ ※ 외부 의존성 없음, 순수 Java 코드 │
└─────────────────────────────────────────────────────────────┘
▲
│ implements
┌─────────────────────────────────────────────────────────────┐
│ Infrastructure Layer │
│ • Repository 구현체 (JPA, Redis) │
│ • 외부 서비스 클라이언트 (Feign) │
│ • 메시징 (Kafka Producer/Consumer) │
└─────────────────────────────────────────────────────────────┘
이 구조에서는 비즈니스 규칙이 수정되더라도 Domain Layer만 수정하면 된다.