Theory
중급 2-3시간 이론

DDD 이론 5: Context Mapping 심화

9가지 Context Map 패턴의 심층 분석, Team Topologies 연계, 실제 기업 사례와 실습을 통해 대규모 시스템의 통합 전략을 마스터합니다.

Context MapPartnershipCustomer-SupplierACLOpen Host ServicePublished LanguageTeam TopologiesConway's Law
학습 목표
  • • Context Map의 본질과 전략적 가치를 이해한다
  • • 9가지 Context Mapping 패턴을 깊이 있게 분석하고 적용할 수 있다
  • • Open Host Service와 Published Language의 실무 구현 방법을 익힌다
  • • Team Topologies와 Context Mapping의 연계를 이해한다
  • • Context Map 시각화 도구와 문서화 방법을 활용할 수 있다
  • • Context Map의 진화와 마이그레이션 전략을 수립할 수 있다
  • • Netflix, Amazon, Shopify 등 실제 기업 사례를 분석할 수 있다
  • • 대규모 시스템의 Context Map을 직접 설계할 수 있다

1. Context Map의 본질과 목적

"Context Map은 프로젝트에 관련된 Bounded Context들과 그들 사이의 관계를 보여주는 문서다. 이것은 현재 상태를 있는 그대로 보여줘야 한다. 이상적인 상태가 아니라."

— Eric Evans, Domain-Driven Design, Chapter 14

1.1 Context Map이란?

Context Map은 시스템 내 모든 Bounded Context와 그들 간의 관계를 시각화한 전략적 설계 도구입니다. 단순한 아키텍처 다이어그램이 아니라, 팀 간의 관계, 권력 구조, 통합 전략을 명시적으로 드러내는 문서입니다.

Context Map이 보여주는 것

🗺️ 기술적 측면

  • • 시스템의 Bounded Context 목록
  • • Context 간 데이터 흐름 방향
  • • 통합 방식 (API, 이벤트, 공유 DB 등)
  • • 의존성 방향과 강도

👥 조직적 측면

  • • 팀 간의 협력 관계
  • • 권력과 협상력의 분포
  • • 의사결정 권한
  • • 커뮤니케이션 패턴

1.2 왜 Context Map이 필요한가?

🔍

현실 파악

시스템의 실제 상태를 명확히 이해. 숨겨진 의존성과 암묵적 결합을 발견.

🗣️

커뮤니케이션 도구

팀 간, 이해관계자 간 공통 언어 제공. 복잡한 시스템을 한눈에 설명.

🎯

전략적 의사결정

어디에 투자할지, 어떤 통합 전략을 선택할지 결정하는 기반.

⚠️

리스크 식별

단일 장애점, 병목 지점, 과도한 결합 등 잠재적 문제 발견.

🚀

진화 계획

현재 상태에서 목표 상태로의 마이그레이션 경로 계획.

1.3 Context Map vs 다른 다이어그램

다이어그램초점Context Map과의 차이
시스템 아키텍처기술 컴포넌트, 인프라팀 관계, 통합 패턴 미포함
ERD데이터 구조, 관계비즈니스 경계, 소유권 미포함
서비스 맵서비스 간 호출 관계협력 패턴, 권력 관계 미포함
조직도팀 구조, 보고 체계시스템 경계, 기술 통합 미포함
Context Map비즈니스 경계 + 팀 관계 + 통합 전략전략적 관점의 통합 뷰

"Context Map은 기술적 다이어그램이 아니다. 그것은 조직의 정치적 지형도다. 누가 누구에게 의존하는지, 누가 협상력을 가지는지를 보여준다."

— Alberto Brandolini, Event Storming 창시자

💡 실무 인사이트

많은 팀이 Context Map을 "있으면 좋은 문서" 정도로 생각합니다. 하지만 실제로는 전략적 의사결정의 핵심 도구입니다. 새로운 기능을 어느 Context에 배치할지, 어떤 팀과 협력해야 할지, 외부 시스템을 어떻게 통합할지 등의 결정에 Context Map이 필수입니다.

2. Context Mapping 패턴 심화

4장에서 9가지 패턴을 개괄적으로 살펴봤습니다. 이번 섹션에서는 각 패턴의실제 구현 방법, 트레이드오프, 진화 전략을 심층적으로 다룹니다.

2.1 협력 패턴 심화

Partnership (파트너십) 심화

두 팀이 공동의 목표를 위해 긴밀하게 협력하는 관계. 인터페이스 변경 시 함께 조율하고, 함께 성공하거나 함께 실패합니다.

성공 조건

  • • 두 팀이 같은 관리자 아래 있거나 긴밀한 관계
  • • 공동 스프린트 계획, 동기화된 릴리스
  • • 정기적인 합동 회의 (주 1회 이상)
  • • 공유된 성공 지표 (KPI)

실패 신호

  • • 한 팀이 다른 팀을 기다리며 블로킹
  • • 인터페이스 변경 시 갈등 발생
  • • 책임 전가, 비난 문화
  • • 릴리스 일정 불일치

구현 패턴

// Partnership: 공유 인터페이스 정의
// 두 팀이 함께 소유하고 변경

// shared-contracts/order-payment.ts
export interface OrderPaymentContract {
  // 버전 관리로 호환성 유지
  version: '2.0';
  
  // 주문 → 결제 요청
  initiatePayment(request: PaymentRequest): Promise<PaymentInitiated>;
  
  // 결제 → 주문 콜백
  onPaymentCompleted(callback: PaymentCompletedHandler): void;
  onPaymentFailed(callback: PaymentFailedHandler): void;
}

// 변경 프로세스:
// 1. 두 팀이 함께 인터페이스 변경 논의
// 2. 공유 저장소에 PR 생성
// 3. 양쪽 팀 리뷰 및 승인
// 4. 동시 배포 또는 하위 호환 유지

⚠️ 주의: Partnership의 함정

Partnership은 유지 비용이 높습니다. 팀 간 조율에 많은 시간이 소요되고, 한 팀의 지연이 다른 팀에 직접 영향을 줍니다.정말 필요한 경우에만 선택하세요.

Shared Kernel (공유 커널) 심화

두 Context가 도메인 모델의 일부를 공유합니다. 공유 부분의 변경은 양쪽 팀의 합의가 필요합니다.

공유 커널 구조

// shared-kernel/
├── domain/
│   ├── Money.ts           // 금액 Value Object
│   ├── Address.ts         // 주소 Value Object
│   ├── DateRange.ts       // 기간 Value Object
│   └── PersonName.ts      // 이름 Value Object
├── events/
│   ├── DomainEvent.ts     // 기본 이벤트 인터페이스
│   └── EventMetadata.ts   // 이벤트 메타데이터
└── types/
    ├── Result.ts          // 결과 타입 (성공/실패)
    └── EntityId.ts        // ID 기본 타입

// 사용 예시
import { Money, Address } from '@company/shared-kernel';

class Order {
  constructor(
    private readonly totalAmount: Money,      // 공유 커널
    private readonly shippingAddress: Address // 공유 커널
  ) {}
}

공유해도 좋은 것

  • • 범용 Value Object (Money, Address)
  • • 기본 이벤트 인터페이스
  • • 공통 유틸리티 타입
  • • 변경 빈도가 낮은 것

공유하면 안 되는 것

  • • Entity (식별성이 Context마다 다름)
  • • 비즈니스 규칙
  • • Context 특화 로직
  • • 자주 변경되는 것

"Shared Kernel은 가능한 작게 유지하라. 공유하는 것이 많아질수록 두 팀의 자율성은 줄어든다."

— Eric Evans

2.2 상류/하류 패턴 심화

Customer-Supplier 심화

Upstream(공급자)이 Downstream(고객)의 요구사항을 수용하는 관계.고객의 요구가 공급자의 백로그에 반영됩니다.

협력 프로세스

Customer-Supplier 협력 프로세스:

1. 요구사항 수집
   Downstream 팀 → Upstream 팀에 API 요구사항 전달
   
2. 우선순위 협상
   양 팀이 함께 우선순위 결정
   Downstream의 비즈니스 가치 고려
   
3. 계약 정의
   Consumer-Driven Contract Testing
   Downstream이 기대하는 계약을 먼저 정의
   
4. 구현 및 검증
   Upstream이 구현
   Downstream의 계약 테스트로 검증
   
5. 배포
   Upstream 먼저 배포 (하위 호환 유지)
   Downstream 이후 배포

Consumer-Driven Contract 예시

// Downstream(Order Context)이 정의하는 계약
// pact/order-product-contract.ts

const productContract = {
  consumer: 'OrderContext',
  provider: 'ProductContext',
  interactions: [
    {
      description: 'get product by id',
      request: {
        method: 'GET',
        path: '/api/products/123'
      },
      response: {
        status: 200,
        body: {
          id: '123',
          name: Matchers.string(),
          price: {
            amount: Matchers.decimal(),
            currency: Matchers.string()
          },
          available: Matchers.boolean()
        }
      }
    }
  ]
};

// Upstream(Product Context)은 이 계약을 만족해야 함
// CI/CD에서 계약 테스트 실행
Conformist vs ACL: 선택 기준
기준ConformistACL
외부 모델 품질좋음, 우리 도메인과 유사나쁨, 우리 도메인과 다름
변경 빈도낮음, 안정적높음, 자주 변경
구현 비용낮음높음 (번역 계층 필요)
유지보수 비용외부 변경에 취약외부 변경 격리
도메인 순수성오염 가능보호됨

💡 실무 가이드라인

  • 표준 프로토콜 (OAuth, OpenID) → Conformist
  • 잘 설계된 외부 API (Stripe, Twilio) → Conformist 또는 얇은 ACL
  • 레거시 시스템 → ACL 필수
  • Core Domain과 통합 → ACL로 보호

3. Open Host Service와 Published Language

"Open Host Service는 여러 클라이언트가 사용할 수 있는 프로토콜을 정의한다. Published Language는 그 프로토콜에서 사용하는 공용 언어다. 이 둘은 함께 사용될 때 가장 강력하다."

— Eric Evans, Domain-Driven Design

3.1 Open Host Service (OHS)

Upstream Context가 여러 Downstream을 위한 표준화된 서비스를 제공합니다. 각 Downstream에 맞춤 API를 만드는 대신, 범용적인 API를 공개합니다.

OHS 아키텍처

                              ┌─────────────────┐
                         ┌───►│  Order Context  │
                         │    └─────────────────┘
┌─────────────────┐      │    ┌─────────────────┐
│ Product Context │──────┼───►│ Search Context  │
│   [Open Host]   │      │    └─────────────────┘
│                 │      │    ┌─────────────────┐
│  REST API v2    │──────┼───►│Analytics Context│
│  GraphQL        │      │    └─────────────────┘
│  Event Stream   │      │    ┌─────────────────┐
└─────────────────┘      └───►│  Mobile App     │
                              └─────────────────┘

특징:
• 하나의 API로 여러 소비자 지원
• 버전 관리로 하위 호환성 유지
• 문서화된 공개 인터페이스

OHS 구현 옵션

  • REST API - 가장 범용적
  • GraphQL - 유연한 쿼리
  • gRPC - 고성능, 타입 안전
  • Event Stream - 비동기 통합
  • Webhook - 푸시 알림

OHS 설계 원칙

  • • 특정 소비자에 종속되지 않음
  • • 명확한 버전 관리 전략
  • • 충분한 문서화
  • • 하위 호환성 우선
  • • Rate Limiting, 인증 포함

3.2 Published Language

Context 간 통신을 위한 잘 문서화된 공용 언어입니다. OHS의 데이터 형식을 정의하고, 모든 참여자가 이해할 수 있는 스키마를 제공합니다.

동기 통신용

  • OpenAPI (Swagger) - REST API 스펙
  • GraphQL Schema - GraphQL 타입 정의
  • Protocol Buffers - gRPC 스키마
  • JSON Schema - JSON 구조 정의

비동기 통신용

  • AsyncAPI - 이벤트 기반 API 스펙
  • Avro - 스키마 진화 지원
  • CloudEvents - 이벤트 표준 형식
  • JSON Schema - 이벤트 페이로드

OpenAPI 예시

# product-api.yaml
openapi: 3.0.3
info:
  title: Product Context API
  version: 2.0.0
  description: |
    상품 정보를 제공하는 Open Host Service.
    모든 소비자는 이 API를 통해 상품 데이터에 접근합니다.

paths:
  /products/{productId}:
    get:
      summary: 상품 상세 조회
      parameters:
        - name: productId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: 성공
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'

components:
  schemas:
    Product:
      type: object
      required: [id, name, price, status]
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          maxLength: 200
        description:
          type: string
        price:
          $ref: '#/components/schemas/Money'
        status:
          type: string
          enum: [ACTIVE, INACTIVE, DISCONTINUED]
        
    Money:
      type: object
      required: [amount, currency]
      properties:
        amount:
          type: number
          format: decimal
        currency:
          type: string
          pattern: '^[A-Z]{3}$'
AsyncAPI로 이벤트 정의
# product-events.yaml
asyncapi: 2.6.0
info:
  title: Product Context Events
  version: 1.0.0

channels:
  product/created:
    publish:
      message:
        $ref: '#/components/messages/ProductCreated'
  
  product/price-changed:
    publish:
      message:
        $ref: '#/components/messages/ProductPriceChanged'

components:
  messages:
    ProductCreated:
      name: ProductCreated
      payload:
        type: object
        required: [eventId, occurredAt, productId, name, price]
        properties:
          eventId:
            type: string
            format: uuid
          occurredAt:
            type: string
            format: date-time
          productId:
            type: string
            format: uuid
          name:
            type: string
          price:
            $ref: '#/components/schemas/Money'
    
    ProductPriceChanged:
      name: ProductPriceChanged
      payload:
        type: object
        required: [eventId, occurredAt, productId, oldPrice, newPrice]
        properties:
          eventId:
            type: string
            format: uuid
          occurredAt:
            type: string
            format: date-time
          productId:
            type: string
            format: uuid
          oldPrice:
            $ref: '#/components/schemas/Money'
          newPrice:
            $ref: '#/components/schemas/Money'
          reason:
            type: string

3.3 스키마 진화 전략

Published Language는 시간이 지나면서 진화합니다.하위 호환성을 유지하면서 스키마를 변경하는 전략이 필요합니다.

✓ 하위 호환 변경 (안전)

  • • 새 필드 추가 (optional)
  • • 새 enum 값 추가
  • • 필드를 optional로 변경
  • • 새 엔드포인트 추가

✗ 하위 비호환 변경 (위험)

  • • 필드 삭제
  • • 필드 타입 변경
  • • 필드를 required로 변경
  • • 필드 이름 변경
  • • enum 값 삭제

버전 관리 전략

URL 버전: /api/v1/products, /api/v2/products

헤더 버전: Accept: application/vnd.company.v2+json

이벤트 버전: ProductCreated.v1, ProductCreated.v2

💡 실무 팁: Schema Registry

이벤트 기반 시스템에서는 Schema Registry를 사용하여 스키마를 중앙에서 관리하세요.

  • Confluent Schema Registry - Kafka와 함께 사용
  • AWS Glue Schema Registry - AWS 환경
  • Apicurio Registry - 오픈소스 옵션

4. 팀 토폴로지와 Context Mapping

"조직의 커뮤니케이션 구조를 설계하는 모든 조직은 그 구조의 복사본인 시스템을 설계하게 된다."

— Melvin Conway, Conway의 법칙 (1967)

4.1 Conway의 법칙과 역 Conway 기동

Conway의 법칙

시스템 구조는 조직 구조를 반영합니다. 팀 간 커뮤니케이션 패턴이 시스템 간 인터페이스가 됩니다.

3개 팀 → 3개 컴포넌트

팀 간 소통 어려움 → 시스템 간 통합 어려움

역 Conway 기동

원하는 시스템 구조에 맞게 조직을 설계합니다. Context Map을 먼저 그리고, 그에 맞게 팀을 구성합니다.

목표 아키텍처 정의 → 팀 구조 조정

Bounded Context = 팀 소유권

4.2 Team Topologies의 4가지 팀 유형

팀 유형과 Context Mapping 패턴

1. Stream-aligned Team (스트림 정렬 팀)

비즈니스 가치 흐름에 정렬된 팀. 하나의 Bounded Context를 소유.

Context Mapping: 다른 Stream-aligned 팀과 Customer-Supplier 또는 Partnership

2. Platform Team (플랫폼 팀)

내부 서비스/플랫폼을 제공하는 팀. 여러 팀이 사용하는 공통 기능.

Context Mapping: Open Host Service + Published Language 제공

3. Enabling Team (지원 팀)

다른 팀의 역량 향상을 돕는 팀. 기술 전문성 전파.

Context Mapping: 직접적인 Context 소유 없음, 다른 팀의 ACL/통합 지원

4. Complicated Subsystem Team (복잡한 서브시스템 팀)

특수 전문성이 필요한 복잡한 컴포넌트를 담당하는 팀.

Context Mapping: OHS로 복잡성 캡슐화, 소비자에게 단순한 인터페이스 제공

4.3 팀 상호작용 모드

상호작용 모드설명Context Mapping 패턴
Collaboration두 팀이 긴밀하게 협력Partnership, Shared Kernel
X-as-a-Service한 팀이 서비스 제공, 다른 팀이 소비OHS + Published Language, Customer-Supplier
Facilitating한 팀이 다른 팀의 역량 향상 지원직접적 패턴 없음 (ACL 구현 지원 등)
팀 토폴로지 + Context Map 예시
┌─────────────────────────────────────────────────────────────────────────┐
│                    E-Commerce Platform Team Topology                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  Stream-aligned Teams (비즈니스 가치 흐름)                                │
│  ┌──────────────┐    Partnership    ┌──────────────┐                    │
│  │  Order Team  │◄────────────────►│ Payment Team │                    │
│  │   (주문 BC)   │                   │  (결제 BC)   │                    │
│  └──────┬───────┘                   └──────────────┘                    │
│         │                                                                │
│         │ Customer-Supplier                                              │
│         ▼                                                                │
│  ┌──────────────┐                   ┌──────────────┐                    │
│  │ Catalog Team │                   │Shipping Team │                    │
│  │  (상품 BC)    │                   │  (배송 BC)   │                    │
│  └──────┬───────┘                   └──────────────┘                    │
│         │                                                                │
│         │ OHS + PL                                                       │
│         ▼                                                                │
│  Platform Team (내부 플랫폼)                                              │
│  ┌──────────────────────────────────────────────────┐                   │
│  │              Platform Team                        │                   │
│  │  ┌────────┐  ┌────────┐  ┌────────┐             │                   │
│  │  │Identity│  │  Event │  │  API   │             │                   │
│  │  │Platform│  │  Bus   │  │Gateway │             │                   │
│  │  └────────┘  └────────┘  └────────┘             │                   │
│  │         [Open Host Service 제공]                 │                   │
│  └──────────────────────────────────────────────────┘                   │
│                                                                          │
│  Enabling Team (역량 지원)                                               │
│  ┌──────────────────────────────────────────────────┐                   │
│  │              DDD/Architecture Team                │                   │
│  │  • Context 경계 설계 지원                          │                   │
│  │  • ACL 구현 가이드                                │                   │
│  │  • Event Storming 퍼실리테이션                    │                   │
│  └──────────────────────────────────────────────────┘                   │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

4.4 인지 부하와 팀 크기

"팀의 인지 부하를 초과하는 Bounded Context를 할당하지 마라. 팀이 감당할 수 있는 복잡도에는 한계가 있다."

— Team Topologies, Matthew Skelton & Manuel Pais

5-9명

이상적인 팀 크기

Two-Pizza Team

1-2개

팀당 Bounded Context

명확한 소유권

2주

의미 있는 기능 배포 주기

독립적 진화

⚠️ 경고: 팀-Context 불일치

다음 상황은 문제의 신호입니다:

  • • 하나의 Context를 여러 팀이 공유 → 소유권 불명확, 충돌
  • • 한 팀이 너무 많은 Context 소유 → 인지 부하 초과
  • • Context 경계와 팀 경계 불일치 → 커뮤니케이션 오버헤드

5. Context Map 시각화와 도구

5.1 Context Map 표기법

표준 표기법
Context Map 표기법 범례:

┌─────────────┐
│   Context   │  박스: Bounded Context
│    Name     │
└─────────────┘

관계 표기:
A ◄──────────► B    Partnership (양방향 화살표)
A ────────────► B    Upstream → Downstream (단방향)
A ──── SK ────► B    Shared Kernel
A ──── ACL ───► B    Anti-Corruption Layer
A ──── OHS ───► B    Open Host Service
A ──── PL ────► B    Published Language
A ──── CF ────► B    Conformist
A ──── CS ────► B    Customer-Supplier

U = Upstream (상류)
D = Downstream (하류)

예시:
┌─────────────┐         ┌─────────────┐
│   Product   │   OHS   │    Order    │
│   Context   │────────►│   Context   │
│     [U]     │   PL    │     [D]     │
└─────────────┘         └─────────────┘

5.2 Context Map 도구

📝 다이어그램 도구

  • Miro/Mural - 협업 화이트보드, Event Storming에 적합
  • Draw.io - 무료, 다양한 템플릿
  • Lucidchart - 전문적인 다이어그램
  • PlantUML - 코드로 다이어그램 생성

🛠️ 전문 도구

  • Context Mapper - DSL 기반 Context Map 모델링
  • Structurizr - C4 모델 + Context Map
  • EventStorming.com - 온라인 Event Storming
  • IcePanel - 아키텍처 시각화 플랫폼
Context Mapper DSL 예시
코드로 Context Map을 정의하고 다이어그램 자동 생성
// ecommerce.cml - Context Mapper DSL
ContextMap ECommerceContextMap {
  type = SYSTEM_LANDSCAPE
  state = AS_IS
  
  contains OrderContext
  contains ProductContext
  contains PaymentContext
  contains ShippingContext
  contains InventoryContext
  
  // 관계 정의
  OrderContext [D,C]<-[U,S] ProductContext {
    implementationTechnology = "REST API"
    exposedAggregates = Product
  }
  
  OrderContext [D]<-[U] PaymentContext {
    implementationTechnology = "Domain Events"
  }
  
  OrderContext Partnership PaymentContext {
    implementationTechnology = "Shared Library"
  }
  
  ShippingContext [D,ACL]<-[U,OHS] ExternalLogisticsAPI {
    implementationTechnology = "REST + ACL"
  }
}

BoundedContext OrderContext implements OrderDomain {
  type = FEATURE
  domainVisionStatement = "주문 생성, 변경, 취소를 담당"
  responsibilities = "Order", "OrderItem", "OrderStatus"
  
  Aggregate Order {
    Entity Order {
      aggregateRoot
      - OrderId id
      - CustomerId customerId
      - List<OrderItem> items
      - OrderStatus status
      - Money totalAmount
    }
  }
}

// 다이어그램 생성 명령
// ./contextmapper generate ecommerce.cml -g plantuml

5.3 Context Map 문서화 템플릿

Context Map 문서 구조

1. 개요

  • • 시스템 이름과 목적
  • • Context Map 버전과 최종 수정일
  • • 작성자와 검토자

2. Context 목록

각 Context에 대해:

  • • 이름과 설명
  • • 소유 팀
  • • 핵심 도메인 개념
  • • 기술 스택
  • • 서브도메인 유형 (Core/Supporting/Generic)

3. 관계 정의

각 관계에 대해:

  • • Upstream/Downstream Context
  • • 패턴 (Partnership, ACL, OHS 등)
  • • 통합 방식 (REST, Event, 공유 DB 등)
  • • 데이터 흐름
  • • SLA/계약

4. 시각적 다이어그램

  • • 전체 Context Map 다이어그램
  • • 데이터 흐름 다이어그램
  • • 팀 소유권 매핑

5. 진화 계획

  • • 현재 상태 (AS-IS)
  • • 목표 상태 (TO-BE)
  • • 마이그레이션 단계
  • • 리스크와 의존성

💡 실무 팁: Context Map을 살아있게 유지하기

  • 코드와 함께 버전 관리 - Context Map을 Git에 저장
  • 정기 리뷰 - 분기별로 Context Map 리뷰 세션
  • 변경 시 업데이트 - 새 Context 추가, 관계 변경 시 즉시 반영
  • 온보딩 자료로 활용 - 새 팀원에게 시스템 설명
  • ADR과 연결 - 아키텍처 결정 기록과 Context Map 연결

6. Context Map 진화와 마이그레이션

6.1 Context Map의 진화

Context Map은 정적인 문서가 아닙니다. 비즈니스가 성장하고, 팀이 변화하고, 기술이 발전함에 따라 지속적으로 진화해야 합니다.

진화 트리거

  • • 새로운 비즈니스 도메인 추가
  • • 팀 구조 변경 (합병, 분리)
  • • 기술 스택 변경
  • • 외부 시스템 통합/제거
  • • 성능/확장성 요구사항 변화
  • • 레거시 시스템 현대화

6.2 패턴 전환 시나리오

일반적인 패턴 전환 경로

시나리오 1: Conformist → ACL

Before:                          After:
┌──────────┐                     ┌──────────┐
│ External │                     │ External │
│   API    │                     │   API    │
└────┬─────┘                     └────┬─────┘
     │ Conformist                     │
     ▼                                ▼
┌──────────┐                     ┌────┴─────┐
│   Our    │         →           │   ACL    │
│ Context  │                     └────┬─────┘
└──────────┘                          │
                                      ▼
                                 ┌──────────┐
                                 │   Our    │
                                 │ Context  │
                                 └──────────┘

언제: 외부 API가 자주 변경되거나, 우리 도메인 모델과 불일치가 커질 때

시나리오 2: Partnership → Customer-Supplier

Before:                          After:
┌──────────┐  Partnership  ┌──────────┐
│ Context  │◄────────────►│ Context  │
│    A     │               │    B     │
└──────────┘               └──────────┘
                    ↓
┌──────────┐  Customer-Supplier  ┌──────────┐
│ Context  │◄────────────────────│ Context  │
│  A [U]   │                     │  B [D]   │
└──────────┘                     └──────────┘

언제: 팀이 분리되거나, 한쪽이 더 안정적인 서비스 제공자 역할을 할 때

시나리오 3: Big Ball of Mud → 여러 Context

Before:                          After:
┌─────────────────────┐          ┌──────────┐    ┌──────────┐
│                     │          │ Context  │◄──►│ Context  │
│   Big Ball of Mud   │    →     │    A     │    │    B     │
│                     │          └──────────┘    └──────────┘
└─────────────────────┘                │              │
                                       └──────┬───────┘
                                              ▼
                                       ┌──────────┐
                                       │ Context  │
                                       │    C     │
                                       └──────────┘

언제: 레거시 현대화, 마이크로서비스 전환 시

6.3 Context 분할 전략

하나의 Context를 여러 개로 분할

분할 신호

  • • 같은 용어가 다른 의미로 사용됨
  • • 팀 내 서로 다른 그룹이 다른 부분을 담당
  • • 변경 주기가 크게 다른 영역 존재
  • • 확장 요구사항이 다른 영역 존재

분할 프로세스

1. 경계 식별
   - Event Storming으로 서브도메인 재발견
   - 언어적 경계 확인
   
2. 내부 모듈화
   - 기존 Context 내에서 모듈로 분리
   - 모듈 간 인터페이스 정의
   
3. 데이터 분리
   - 공유 테이블 식별
   - 각 모듈 전용 테이블로 분리
   
4. API 분리
   - 모듈별 API 엔드포인트 분리
   - 내부 통신을 API 호출로 전환
   
5. 물리적 분리 (선택)
   - 별도 서비스로 배포
   - Context Map 업데이트

6.4 Context 병합 전략

여러 Context를 하나로 병합

병합 신호

  • • 두 Context가 항상 함께 변경됨
  • • 과도한 Context 간 통신 오버헤드
  • • 분산 트랜잭션 문제 빈발
  • • 팀 병합으로 인한 조직 변화
  • • 너무 작은 Context로 인한 운영 부담

⚠️ 병합 시 주의사항

  • • 마이크로서비스 병합은 매우 어려움
  • • 데이터 마이그레이션 복잡도 높음
  • • 모듈러 모놀리스에서는 상대적으로 쉬움
  • • 병합 전 충분한 분석 필요
AS-IS → TO-BE 마이그레이션 예시

AS-IS (현재)

┌─────────────────────┐
│   Monolith          │
│  ┌─────┐ ┌─────┐   │
│  │Order│─│Pay  │   │
│  └─────┘ └─────┘   │
│  ┌─────┐ ┌─────┐   │
│  │Prod │─│Ship │   │
│  └─────┘ └─────┘   │
│     Shared DB      │
└─────────────────────┘

문제:
• 모든 것이 결합
• 독립 배포 불가
• 확장 어려움

TO-BE (목표)

┌───────┐   ┌───────┐
│ Order │◄─►│Payment│
│Context│   │Context│
└───┬───┘   └───────┘
    │ CS
    ▼
┌───────┐   ┌───────┐
│Product│   │Shipping│
│Context│   │Context │
└───────┘   └───┬───┘
                │ ACL
                ▼
           ┌────────┐
           │External│
           │Logistics│
           └────────┘

개선:
• 독립적 Context
• 명확한 관계
• 독립 배포 가능

💡 마이그레이션 원칙

  • 점진적 진행 - Big Bang 마이그레이션 피하기
  • 롤백 가능 - 각 단계에서 롤백 계획 수립
  • 비즈니스 연속성 - 마이그레이션 중에도 서비스 유지
  • 측정 가능 - 성공 지표 정의 및 모니터링

7. 실제 기업 사례 심층 분석

7.1 Netflix의 Context Mapping

🎬 Netflix 아키텍처
Netflix Context Map (간략화)

┌─────────────────────────────────────────────────────────────────┐
│                     API Gateway (Zuul)                          │
└─────────────────────────────────────────────────────────────────┘
         │              │              │              │
         ▼              ▼              ▼              ▼
┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│  Streaming  │  │Recommendation│  │Subscription │  │   Content   │
│   Context   │  │   Context   │  │   Context   │  │   Context   │
│             │  │   (Core)    │  │             │  │             │
│ • Playback  │  │ • ML Models │  │ • Billing   │  │ • Catalog   │
│ • Encoding  │  │ • User Pref │  │ • Plans     │  │ • Metadata  │
│ • CDN       │  │ • A/B Test  │  │ • Payment   │  │ • Licensing │
└──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘
       │                │                │                │
       │    OHS + PL    │    OHS + PL    │    ACL        │
       │                │                │                │
       └────────────────┴────────────────┴────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │   Data Platform     │
                    │  (Event Sourcing)   │
                    └─────────────────────┘

적용 패턴

  • OHS + PL: 각 서비스가 gRPC/REST API 공개
  • ACL: 외부 결제 시스템 통합
  • Published Language: Protobuf 스키마
  • Separate Ways: 지역별 독립 시스템

핵심 원칙

  • • 팀 자율성 최대화
  • • 각 팀이 자신의 API 소유
  • • Chaos Engineering으로 장애 격리 검증
  • • 이벤트 기반 데이터 동기화

7.2 Amazon의 Context Mapping

🛒 Amazon 아키텍처

"Amazon은 2002년에 이미 서비스 지향 아키텍처로 전환했다. 모든 팀은 서비스 인터페이스를 통해서만 통신해야 한다."

— Jeff Bezos의 API Mandate (2002)

Amazon E-Commerce Context Map (간략화)

┌─────────────────────────────────────────────────────────────────┐
│                        Customer Experience                       │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │
│  │  Search  │  │  Browse  │  │   Cart   │  │ Checkout │        │
│  │ Context  │  │ Context  │  │ Context  │  │ Context  │        │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘        │
└───────┼─────────────┼─────────────┼─────────────┼───────────────┘
        │             │             │             │
        │ CS          │ CS          │ Partnership │
        ▼             ▼             ▼             ▼
┌─────────────────────────────────────────────────────────────────┐
│                         Core Commerce                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │
│  │ Catalog  │  │  Order   │  │ Payment  │  │ Inventory│        │
│  │ Context  │  │ Context  │  │ Context  │  │ Context  │        │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘        │
└───────┼─────────────┼─────────────┼─────────────┼───────────────┘
        │             │             │             │
        │ OHS         │ Events      │ ACL         │ CS
        ▼             ▼             ▼             ▼
┌─────────────────────────────────────────────────────────────────┐
│                         Fulfillment                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │
│  │Warehouse │  │ Shipping │  │  Returns │  │ Logistics│        │
│  │ Context  │  │ Context  │  │ Context  │  │ Context  │        │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘        │
└─────────────────────────────────────────────────────────────────┘

Amazon의 핵심 원칙

  • Two-Pizza Team: 각 팀이 하나의 Context 소유
  • You Build It, You Run It: 개발팀이 운영까지 책임
  • API First: 모든 통신은 API를 통해서만
  • Backward Compatibility: API 하위 호환성 필수

7.3 Shopify의 모듈러 모놀리스

🛍️ Shopify 아키텍처

"우리는 마이크로서비스의 복잡성 없이 Bounded Context의 이점을 얻기 위해 모듈러 모놀리스를 선택했다."

— Shopify Engineering Blog (2024)

Shopify Modular Monolith

┌─────────────────────────────────────────────────────────────────┐
│                    Single Rails Application                      │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                    Public API Layer                       │   │
│  └──────────────────────────────────────────────────────────┘   │
│                              │                                   │
│  ┌──────────┐  ┌──────────┐  │  ┌──────────┐  ┌──────────┐     │
│  │  Orders  │  │ Products │  │  │ Payments │  │ Shipping │     │
│  │  Module  │  │  Module  │  │  │  Module  │  │  Module  │     │
│  │          │  │          │  │  │          │  │          │     │
│  │ [Context]│  │ [Context]│  │  │ [Context]│  │ [Context]│     │
│  └────┬─────┘  └────┬─────┘  │  └────┬─────┘  └────┬─────┘     │
│       │             │        │       │             │            │
│       └─────────────┴────────┴───────┴─────────────┘            │
│                              │                                   │
│                    Internal Module APIs                          │
│                    (Packwerk로 경계 강제)                         │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                    Shared Database                        │   │
│  │              (스키마는 모듈별로 분리)                       │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Packwerk 규칙:
• 모듈 간 직접 참조 금지
• 공개 API를 통해서만 통신
• 의존성 방향 강제

장점

  • • 단순한 배포 (하나의 앱)
  • • 트랜잭션 처리 용이
  • • 리팩토링 쉬움
  • • 운영 복잡도 낮음

도구

  • Packwerk: 모듈 경계 강제
  • Sorbet: 타입 체크
  • Delorean: 데이터 분리

7.4 국내 사례: 배달의민족

🍔 배달의민족 아키텍처
배달의민족 Context Map (공개 정보 기반)

┌─────────────────────────────────────────────────────────────────┐
│                         고객 접점                                │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                      │
│  │   검색   │  │   주문   │  │   리뷰   │                      │
│  │ Context  │  │ Context  │  │ Context  │                      │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘                      │
└───────┼─────────────┼─────────────┼─────────────────────────────┘
        │             │             │
        │ Events      │ Partnership │ Events
        ▼             ▼             ▼
┌─────────────────────────────────────────────────────────────────┐
│                         핵심 도메인                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐        │
│  │   가게   │  │   메뉴   │  │   결제   │  │   정산   │        │
│  │ Context  │  │ Context  │  │ Context  │  │ Context  │        │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘        │
└───────┼─────────────┼─────────────┼─────────────┼───────────────┘
        │             │             │             │
        │ OHS         │ Events      │ ACL         │ Events
        ▼             ▼             ▼             ▼
┌─────────────────────────────────────────────────────────────────┐
│                         배달 도메인                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                      │
│  │  라이더  │  │   배차   │  │   추적   │                      │
│  │ Context  │  │ Context  │  │ Context  │                      │
│  └──────────┘  └──────────┘  └──────────┘                      │
└─────────────────────────────────────────────────────────────────┘

핵심 전략

  • 이벤트 기반: Kafka를 통한 Context 간 통신
  • CQRS: 읽기/쓰기 분리로 성능 최적화
  • 점진적 전환: 2년에 걸친 마이크로서비스 전환
  • 팀 자율성: 각 Context를 독립 팀이 소유

8. 실습: 대규모 시스템 Context Map 설계

🎯 워크숍: 온라인 교육 플랫폼
온라인 교육 플랫폼의 Context Map을 설계하고, 팀 구조와 통합 전략을 정의합니다.

8.1 비즈니스 요구사항

핵심 기능

  • • 강의 콘텐츠 관리 및 스트리밍
  • • 수강 신청 및 결제
  • • 학습 진도 추적
  • • 퀴즈 및 과제 평가
  • • 수료증 발급
  • • 강사-학생 Q&A

비기능 요구사항

  • • 동시 접속 10만 명 지원
  • • 글로벌 서비스 (다국어)
  • • 99.9% 가용성
  • • 외부 결제 시스템 연동
  • • 기업 고객용 SSO 지원

8.2 식별된 Bounded Context

Core

📚 콘텐츠 Context

  • • 강의, 섹션, 레슨
  • • 비디오 메타데이터
  • • 강의 자료
Core

📊 학습 Context

  • • 학습 진도
  • • 완료 기록
  • • 학습 분석
Core

📝 평가 Context

  • • 퀴즈, 과제
  • • 채점, 피드백
  • • 수료 기준
Supporting

🛒 수강 Context

  • • 수강 신청
  • • 수강 권한
  • • 환불 처리
Supporting

🎓 수료증 Context

  • • 수료증 생성
  • • 검증 서비스
  • • 블록체인 기록
Supporting

💬 커뮤니티 Context

  • • Q&A 게시판
  • • 토론
  • • 리뷰
Generic

👤 Identity Context

  • • 인증/인가
  • • SSO 연동
  • • 프로필
Generic

💳 결제 Context

  • • 결제 처리
  • • 구독 관리
  • • 정산
Generic

🔔 알림 Context

  • • 이메일/푸시
  • • 알림 설정
  • • 템플릿

8.3 Context Map

온라인 교육 플랫폼 Context Map

┌─────────────────────────────────────────────────────────────────────────┐
│                           External Systems                               │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐                │
│  │  Stripe  │  │  Auth0   │  │   CDN    │  │  Twilio  │                │
│  │   (PG)   │  │  (IdP)   │  │(Cloudflare)│ │  (SMS)   │                │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘                │
│       │ACL          │CF           │OHS          │ACL                    │
└───────┼─────────────┼─────────────┼─────────────┼───────────────────────┘
        │             │             │             │
        ▼             ▼             ▼             ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          Platform Layer                                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐                │
│  │  결제    │  │ Identity │  │ 스트리밍  │  │   알림   │                │
│  │ Context  │  │ Context  │  │ Context  │  │ Context  │                │
│  │  [OHS]   │  │  [OHS]   │  │  [OHS]   │  │  [OHS]   │                │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘                │
└───────┼─────────────┼─────────────┼─────────────┼───────────────────────┘
        │             │             │             │
        │ CS          │ OHS         │ CS          │ Events
        ▼             ▼             ▼             ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                           Core Domain                                    │
│                                                                          │
│  ┌──────────┐    Partnership    ┌──────────┐    Partnership             │
│  │  콘텐츠  │◄─────────────────►│   학습   │◄─────────────────┐         │
│  │ Context  │                   │ Context  │                  │         │
│  │  [U]     │                   │          │                  │         │
│  └────┬─────┘                   └────┬─────┘                  │         │
│       │                              │                        │         │
│       │ CS                           │ CS                     │         │
│       ▼                              ▼                        ▼         │
│  ┌──────────┐                   ┌──────────┐           ┌──────────┐    │
│  │  수강    │                   │   평가   │           │  수료증  │    │
│  │ Context  │                   │ Context  │           │ Context  │    │
│  │  [D]     │                   │  [D]     │           │  [D]     │    │
│  └──────────┘                   └────┬─────┘           └──────────┘    │
│                                      │                                  │
│                                      │ Events                           │
│                                      ▼                                  │
│                                 ┌──────────┐                           │
│                                 │ 커뮤니티 │                           │
│                                 │ Context  │                           │
│                                 └──────────┘                           │
└─────────────────────────────────────────────────────────────────────────┘

관계 요약:
• 콘텐츠 ↔ 학습: Partnership (긴밀한 협력)
• 학습 ↔ 평가: Partnership (학습 완료 시 평가)
• 학습 → 수료증: Customer-Supplier (수료 조건 충족 시)
• 콘텐츠 → 수강: Customer-Supplier (수강 권한 확인)
• 평가 → 커뮤니티: Events (과제 제출 시 토론 생성)
• 모든 Context → 알림: Events (알림 발송)

8.4 팀 구조 매핑

소유 Context팀 유형규모
콘텐츠팀콘텐츠 ContextStream-aligned6명
학습경험팀학습 + 평가 ContextStream-aligned8명
커머스팀수강 + 결제 ContextStream-aligned5명
플랫폼팀Identity + 알림 + 스트리밍Platform7명
커뮤니티팀커뮤니티 + 수료증Stream-aligned4명

💡 설계 결정 근거

  • 콘텐츠-학습 Partnership: 강의 구조 변경 시 학습 진도 로직도 함께 변경 필요
  • 플랫폼팀 OHS: 여러 팀이 공통으로 사용하는 기능을 표준 API로 제공
  • 외부 시스템 ACL: Stripe, Auth0 등 외부 API 변경으로부터 도메인 보호
  • 이벤트 기반 알림: 모든 Context의 중요 이벤트를 구독하여 알림 발송

9. 자주 묻는 질문 (FAQ)

Q1: Context Map과 시스템 아키텍처 다이어그램의 차이점은?

시스템 아키텍처 다이어그램은 기술적 구성요소(서버, DB, 네트워크)를 보여주고, Context Map은 비즈니스 도메인 간의 관계와 팀 간 협력 방식을 표현합니다. Context Map은 '왜 이렇게 통합하는가'에 대한 조직적, 정치적 맥락을 포함합니다.

Q2: 모든 Bounded Context 간 관계를 Context Map에 표시해야 하나요?

아니요. 실제로 통합이 발생하는 관계만 표시합니다. 독립적으로 운영되는 Context는 Separate Ways로 명시하거나 생략할 수 있습니다.

Q3: ACL(Anti-Corruption Layer)은 언제 사용해야 하나요?

레거시 시스템과 통합할 때, 외부 서비스의 모델이 우리 도메인과 맞지 않을 때, Upstream의 변경으로부터 보호가 필요할 때, Conformist 패턴이 도메인 무결성을 해칠 때 사용합니다.

Q4: Partnership과 Shared Kernel 중 어떤 것을 선택해야 하나요?

Partnership은 두 팀이 긴밀히 협력하지만 각자의 모델을 유지할 때, Shared Kernel은 공통 모델을 실제로 공유하고 함께 변경할 때 사용합니다. Shared Kernel은 강한 결합을 만들므로 정말 필요한 경우에만 사용하세요.

Q5: Context Map은 얼마나 자주 업데이트해야 하나요?

새로운 Bounded Context가 추가될 때, 팀 구조가 변경될 때, 통합 패턴이 변경될 때, 그리고 분기별 정기 리뷰 시점에 업데이트를 권장합니다.

Q6: 마이크로서비스 없이도 Context Mapping이 의미가 있나요?

네. 모놀리스 내에서도 모듈 간 경계와 의존성을 명확히 하는 데 Context Map이 유용합니다. 오히려 마이크로서비스로 전환하기 전에 Context Map을 먼저 그리는 것이 좋습니다.

Q7: Open Host Service와 일반 API의 차이점은?

일반 API는 특정 클라이언트를 위한 맞춤형 인터페이스이고, OHS는 다수의 클라이언트를 위한 표준화된 프로토콜입니다. OHS는 Published Language와 함께 사용되어 명확한 계약을 제공합니다.

Q8: Big Ball of Mud를 어떻게 Context Map으로 표현하나요?

Big Ball of Mud는 그 자체로 하나의 Context로 표시합니다. 다른 Context와의 관계에서는 주로 ACL을 사용하여 오염을 방지하고, 점진적으로 Strangler Fig 패턴을 적용하며 Context Map을 업데이트합니다.

10. 핵심 요약

🗺️ Context Map의 본질
  • • 시스템의 현재 상태를 있는 그대로 표현
  • • 기술적 + 조직적 관계를 모두 포함
  • • 팀 간 커뮤니케이션의 기반
  • • 진화하는 살아있는 문서
🔗 9가지 통합 패턴
  • 협력형: Partnership, Shared Kernel
  • 상하관계: Customer-Supplier, Conformist
  • 보호형: ACL, OHS/PL
  • 독립형: Separate Ways, Big Ball of Mud
👥 Team Topologies 연계
  • • Stream-aligned → Core Domain 담당
  • • Platform → OHS/PL 제공
  • • Enabling → Partnership 촉진
  • • Complicated-subsystem → ACL 뒤 전문 영역
📈 실무 적용 포인트
  • • 현재 상태 먼저, 목표 상태는 나중에
  • • 패턴 선택은 기술 + 조직 + 정치 고려
  • • 정기적 리뷰와 업데이트 필수
  • • 도구보다 팀 간 대화가 중요
"Context Map은 단순한 다이어그램이 아니라,
조직이 소프트웨어를 어떻게 만들고 있는지에 대한 솔직한 대화입니다."

— Eric Evans

11. 참고 자료 및 다음 학습

📚 필수 도서
  • Domain-Driven Design

    Eric Evans - Context Mapping 원전

  • Implementing Domain-Driven Design

    Vaughn Vernon - 실무 적용 가이드

  • Team Topologies

    Matthew Skelton - 팀 구조와 Context 연계

  • Learning Domain-Driven Design

    Vlad Khononov - 현대적 접근법

🔧 도구 및 리소스
  • Context Mapper

    contextmapper.org - DSL 기반 모델링

  • Miro / FigJam

    협업 기반 Context Map 시각화

  • EventStorming

    eventstorming.com - 도메인 발견 워크샵

  • DDD Crew GitHub

    github.com/ddd-crew - 템플릿 모음

🎯 다음 학습 단계

1단계: 실습

  • • 현재 시스템 Context Map 그리기
  • • 팀과 함께 리뷰하기
  • • 문제 영역 식별하기

2단계: 심화

  • • Event Storming 워크샵
  • • ACL 구현 패턴 학습
  • • 이벤트 기반 통합 설계

3단계: 적용

  • • 목표 Context Map 설계
  • • 마이그레이션 계획 수립
  • • 점진적 개선 실행

💡 이 시리즈의 다음 내용

  • DDD Theory 06: Aggregate와 일관성 경계
  • DDD Theory 07: Domain Events와 이벤트 소싱
  • DDD Theory 08: CQRS 패턴 심화