DDD
전략적 설계
Domain-Driven Design의 전략적 패턴 - Bounded Context, Ubiquitous Language, Context Map
Bounded Context (경계 컨텍스트)
도메인을 명확하게 분리하는 경계
Bounded Context는 특정 도메인 모델이 적용되는 명시적 경계입니다. 같은 용어라도 컨텍스트에 따라 다른 의미를 가질 수 있으며, 각 컨텍스트 내에서 모델은 완전하고 일관된 의미를 갖습니다.
가격, 할인, 리뷰 포함
무게, 크기, 취급주의 포함
같은 "Product"라는 단어도 Sales Context에서는 가격과 할인 정보가 중요하고, Shipping Context에서는 무게와 크기가 중요합니다. 이렇게 컨텍스트마다 다른 관점과 속성을 갖기 때문에 경계를 명확히 해야 합니다.
Ubiquitous Language (보편 언어)
개발자와 도메인 전문가가 공유하는 언어
Ubiquitous Language는 개발팀과 도메인 전문가가 함께 사용하는 공통 언어입니다. 이 언어는 코드, 문서, 대화 모든 곳에서 일관되게 사용되어야 하며, 각 Bounded Context 내에서 명확한 의미를 가져야 합니다.
| 용어 | Context | 정의 | 코드 예시 |
|---|---|---|---|
| Order | Sales | 고객이 구매를 확정한 상품 목록과 결제 정보 | class Order { items, customer, totalPrice } |
| Shipment | Shipping | 배송되어야 할 패키지와 배송 상태 정보 | class Shipment { packages, status, carrier } |
| StockItem | Inventory | 창고에 보관 중인 상품의 수량과 위치 | class StockItem { quantity, location, sku } |
| Invoice | Billing | 고객에게 청구할 금액과 결제 내역 | class Invoice { amount, dueDate, lineItems } |
| Customer | Sales | 구매 이력과 선호도를 가진 구매자 | class Customer { preferences, orderHistory } |
| Account | Billing | 결제 수단과 잔액을 관리하는 계정 | class Account { balance, paymentMethods } |
- 일관성 — 코드, 문서, 대화에서 같은 용어를 같은 의미로 사용
- 명확성 — 모호한 표현 대신 구체적이고 명확한 용어 사용
- 진화 — 도메인 이해가 깊어지면 언어도 함께 발전
- 컨텍스트 한정 — 각 Bounded Context 내에서만 유효
Context Map (컨텍스트 맵)
Bounded Context 간의 관계를 정의하는 패턴들
Partnership
두 팀이 협력하여 인터페이스를 함께 발전시킵니다. 성공과 실패를 공유하며, 함께 계획하고 개발합니다.
Customer-Supplier
Upstream(공급자)이 Downstream(고객)의 요구를 수용합니다. 공급자가 API를 제공하고, 고객이 이를 사용합니다.
Conformist
Downstream이 Upstream의 모델을 그대로 따릅니다. Upstream이 변경의 주도권을 가지며, Downstream은 적응합니다.
Anti-Corruption Layer
외부 시스템의 모델이 내부로 침투하지 않도록 번역 레이어를 둡니다. 레거시 시스템 통합에 주로 사용됩니다.
Open Host Service
잘 문서화된 공개 프로토콜을 제공합니다. 여러 Downstream이 쉽게 통합할 수 있는 표준 API입니다.
Published Language
공유된 언어로 데이터를 교환합니다. JSON Schema, Protocol Buffers 등을 활용합니다.
Shared Kernel
두 컨텍스트가 일부 모델을 공유합니다. 변경 시 양쪽 팀의 합의가 필요하며, 신중하게 사용해야 합니다.
Separate Ways
통합하지 않고 각자의 길을 갑니다. 통합 비용이 이점보다 클 때 선택합니다.
인터랙티브 Context Map 예시
E-Commerce 시스템의 Context Map
📤 Upstream: Sales Context
- 주문 완료 이벤트 발행
- 배송 주소 정보 제공
- 배송 요청 API 호출
📥 Downstream: Shipping Context
- 주문 정보를 배송 정보로 변환
- 배송 상태 업데이트 제공
- Anti-Corruption Layer로 보호
Sales가 Supplier로서 주문 정보를 제공하고, Shipping이 Customer로서 이를 소비합니다.
🛒 Sales Context
- 주문 금액 정보 공유
- 할인/쿠폰 적용 정보
- 결제 요청 트리거
💳 Billing Context
- 결제 처리 및 결과 반환
- 청구서 생성
- 환불 처리
두 팀이 긴밀하게 협력하여 결제 흐름을 함께 설계하고 발전시킵니다.
📦 Inventory Context (OHS)
- 재고 현황 API 제공
- 창고 위치 정보 제공
- 표준화된 인터페이스
🚚 Shipping Context
- 픽업 위치 조회
- 재고 가용성 확인
- 배송 경로 최적화
Inventory가 표준 API를 제공하여 여러 컨텍스트가 쉽게 통합할 수 있습니다.
도메인 분석 프로세스
Bounded Context를 발견하는 방법
Event Storming
도메인 전문가와 함께 비즈니스 이벤트를 포스트잇으로 나열하고 시간순으로 배열합니다. "주문 생성됨", "결제 완료됨", "배송 시작됨" 등의 이벤트를 발견합니다.
핵심 도메인 식별
비즈니스에 가장 중요한 핵심 도메인(Core Domain)과 지원 도메인(Supporting Domain), 일반 도메인(Generic Domain)을 구분합니다.
언어적 경계 발견
같은 용어가 다른 의미로 사용되는 지점을 찾습니다. 이 언어적 단절이 Bounded Context의 자연스러운 경계가 됩니다.
팀 구조 고려
Conway's Law를 고려하여 팀 구조와 Context 경계를 맞춥니다. 하나의 팀이 하나의 Bounded Context를 소유하는 것이 이상적입니다.
Context Map 작성
발견된 Context들 간의 관계를 정의합니다. 어떤 패턴(Partnership, Customer-Supplier 등)으로 통합할지 결정합니다.
Bounded Context는 마이크로서비스와 1:1 매핑되지 않을 수 있습니다. 하나의 Context가 여러 서비스로 나뉘거나, 여러 Context가 하나의 서비스에 있을 수 있습니다. 중요한 것은 논리적 경계이지, 물리적 배포 단위가 아닙니다.
핵심 요약
- Bounded Context — 특정 도메인 모델이 적용되는 명시적 경계
- Ubiquitous Language — 개발팀과 도메인 전문가가 공유하는 일관된 언어
- Context Map — Bounded Context 간의 관계를 정의하는 다양한 패턴
- 같은 용어, 다른 의미 — 컨텍스트에 따라 같은 단어도 다른 속성과 행위를 가짐
- Event Storming — 도메인 전문가와 함께 Context 경계를 발견하는 기법
- 팀 구조 정렬 — 하나의 팀이 하나의 Bounded Context를 소유하는 것이 이상적