Phase 4레슨 20

Domain-Driven Design (DDD)

Bounded Context, Aggregate, Value Object, Domain Event, Ubiquitous Language

💡ELI5·

User는 누구인가 — Bounded Context

        "User" 라는 단어
             /   |   \
  주문 컨텍스트  배송 컨텍스트  마케팅 컨텍스트
     구매자       수령인       타겟 고객
  (id, 결제수단) (주소, 연락처) (세그먼트, 행동)

  각 컨텍스트는 User의 다른 측면만 본다.
  하나의 User 테이블이 아니라, 컨텍스트별 모델.
💡 비유한 사람이 집에서는 '아빠', 회사에서는 '과장님', 동호회에서는 '회장'. 맥락에 따라 다른 역할과 속성. DDD는 이 맥락(Bounded Context)을 명시적으로 구분한다.
🔬Deep Dive·

Aggregate와 Root

Order (Aggregate Root)
  ├── id: OrderId
  ├── customer: CustomerId (참조만, Customer Aggregate 직접 접근 X)
  ├── status: OrderStatus
  ├── orderLines: OrderLine[]   ← Order 안에서만 유효
  │     ├── productId
  │     ├── quantity
  │     └── price
  └── shippingAddress: Address  ← Value Object

규칙:
  - 외부에서 OrderLine에 직접 접근 불가 (Root 경유)
  - 한 트랜잭션 = 한 Aggregate 변경
  - 다른 Aggregate는 ID 참조만
규칙이유
Root 경유 접근일관성(불변식) 보장
ID 참조만 (객체 직접 참조 X)Aggregate 간 결합 최소화
한 트랜잭션 = 한 Aggregate트랜잭션 범위 작게 유지
Cross-Aggregate는 Domain Event느슨한 결합, 최종 일관성
🔬Deep Dive·

Entity vs Value Object

구분EntityValue Object
식별ID로 식별속성 값으로 식별
가변성가변 (속성 변경 가능)불변 (새 객체 생성)
동등성ID 비교 (equals by id)속성 비교 (equals by value)
예시User, Order, ProductMoney, Address, DateRange
생명주기독립적 (추적 가능)Entity에 속함 (독립 추적 X)
// Value Object (불변, 속성 비교)
class Money {
  constructor(readonly amount: number, readonly currency: string) {}
  add(other: Money): Money {
    if (this.currency !== other.currency) throw new Error('통화 불일치');
    return new Money(this.amount + other.amount, this.currency); // 새 객체
  }
  equals(other: Money): boolean {
    return this.amount === other.amount && this.currency === other.currency;
  }
}

// Entity (ID 식별, 가변)
class Order {
  constructor(readonly id: OrderId, private status: OrderStatus) {}
  cancel() { this.status = OrderStatus.CANCELLED; } // 상태 변경
}
🔬Deep Dive·

Domain Event — 컨텍스트 간 통신

Order Context:
  Order.cancel() → OrderCancelledEvent 발행

Shipping Context (구독):
  OrderCancelledEvent 수신 → 배송 취소

Marketing Context (구독):
  OrderCancelledEvent 수신 → 이탈 고객 캠페인 트리거

→ Order는 Shipping/Marketing을 모름 (느슨한 결합)
⚖️Trade-off·

DDD의 장단점

장점단점
비즈니스와 코드가 일치 (Ubiquitous Language)학습 곡선 가파름
복잡한 도메인을 명확히 모델링단순 CRUD에 과도함
Bounded Context가 모듈/서비스 경계도메인 전문가와의 긴밀 협업 필요
테스트 용이 (도메인이 외부에 독립)설계 시간 많이 소요
DDD는 복잡한 비즈니스 도메인에 투자할 가치가 있다. 단순한 CRUD 블로그에는 Layered Architecture로 충분하다.

❓ 체크포인트 질문

  1. 1.Bounded Context가 무엇이고 왜 중요한가?
  2. 2.Aggregate와 Aggregate Root의 역할은?
  3. 3.Value Object와 Entity의 차이는?
  4. 4.Ubiquitous Language가 왜 중요한가?
  5. 5.Domain Event가 시스템 분리에 어떻게 기여하는가?