DDD - 에릭 에반스, (14장 모델의 무결성 유지)

2024. 6. 29. 14:49· 도서
목차
  1. Bounded Context (제한된 컨텍스트)
  2. 제한된 컨텍스트(Bounded Context)
  3. 제한된 컨텍스트의 장점
  4. 제한된 컨텍스트 안의 균열 인식
  5. 예제
  6. 균열 인식과 해결 방법
  7. Countinous Integration (지속적인 통합)
  8. 지속적인 통합(Continuous Integration)의 핵심 개념
  9. 지속적인 통합의 장점
  10. 지속적인 통합의 구현 예
  11. 지속적인 통합의 베스트 프랙티스
  12. Conext Map (컨텍스트 맵)
  13. 컨텍스트 맵(Context Map)이란?
  14. 컨텍스트 경계에서의 테스트
  15. 컨텍스트 맵의 조직화와 문서화
  16. Bounded Context 간의 관계
  17. 제한된 컨텍스트 간의 관계 유형
  18. 제한된 컨텍스트 간의 관계 예제
  19. Shared Kernel (공유 커널)
  20. 공유 커널(Shared Kernel) 정의
  21. 공유 커널의 특징
  22. 공유 커널의 장점
  23. 공유 커널의 단점
  24. 공유 커널 예제
  25. Customer/Supplier Development Teams (고객/공급자 개발 팀)
  26. 고객/공급자 개발 팀(Customer/Supplier Development Teams) 정의
  27. 고객/공급자 관계의 특징
  28. 예제: 온라인 쇼핑몰에서의 고객/공급자 관계
  29. Conformist (준수자)
  30. 준수자(Conformist) 정의
  31. 준수자의 특징
  32. 준수자 예제
  33. Anti-corruption Layer (오류 방지 계층)
  34. 오류 방지 계층(Anti-Corruption Layer, ACL) 정의
  35. 오류 방지 계층의 특징
  36. 오류 방지 계층의 장점
  37. 오류 방지 계층의 인터페이스 설계
  38. 코드 예제: Java
  39. Separate Ways (각자의 길)
  40. 각자의 길(Separate Ways) 패턴 정의
  41. 각자의 길 패턴의 특징
  42. 예제: 온라인 쇼핑몰
  43. Open Host Service(공개 호스트 서비스) - 표준화된 서비스 형식
  44. 공개 호스트 서비스(Open Host Service) 정의
  45. 공개 호스트 서비스의 특징
  46. 예제: 온라인 쇼핑몰과 결제 시스템 통합
  47. Published Language (공표된 언어) - 표준화된 데이터 형식
  48. 공표된 언어(Published Language) 정의
  49. 공표된 언어의 특징
  50. 예제: 온라인 쇼핑몰과 결제 시스템 통합
반응형

Bounded Context (제한된 컨텍스트)

제한된 컨텍스트(Bounded Context)

  • 제한된 컨텍스트는 도메인 모델의 경계를 정의하는 개념
  • 각 컨텍스트는 고유한 모델을 가지며, 그 모델은 해당 컨텍스트 내에서만 일관성을 유지한다.
  • 이는 복잡한 도메인 모델을 관리하기 쉽게 만드는 데 중요한 역할을 한다.

제한된 컨텍스트의 장점

  • 일관성 유지: 각 컨텍스트 내에서 모델의 일관성을 유지할 수 있다. 이는 도메인 모델이 정확하고 신뢰할 수 있도록 만든다
  • 독립적인 개발: 각 컨텍스트는 독립적으로 개발되고 유지보수될 수 있다. 이는 개발팀 간의 협업을 촉진하고, 시스템의 유연성을 높인다.
  • 복잡성 관리: 도메인 모델을 작은 부분으로 분할하여, 각 부분의 복잡성을 관리할 수 있다. 이는 시스템의 이해도와 유지보수성을 높인다.

제한된 컨텍스트 안의 균열 인식

  • 제한된 컨텍스트 안의 균열 인식은 컨텍스트 내부에서 발생할 수 있는 모델의 일관성 문제를 인식하고 해결하는 과정
  • 균열 인식의 중요성: 균열을 인식하고 해결함으로써 모델의 일관성과 신뢰성을 유지할 수 있다. 이는 도메인 모델이 정확하게 동작하고, 비즈니스 요구사항을 충족하도록 한다.

예제

  • 주문 처리 컨텍스트에서 주문 상태를 관리할 때, 주문 상태 변경 로직이 복잡해지면 일관성 문제가 발생할 수 있다.
  • 이를 인식하고 해결하기 위해 상태 변경 로직을 단순화하거나, 명확한 규칙을 정의할 수 있다.
public class Order {
    private OrderStatus status;

    public void changeStatus(OrderStatus newStatus) {
        if (status.canChangeTo(newStatus)) {
            this.status = newStatus;
        } else {
            throw new IllegalStateException("Cannot change status from " + status + " to " + newStatus);
        }
    }
}

public enum OrderStatus {
    NEW, PROCESSING, SHIPPED, DELIVERED;

    public boolean canChangeTo(OrderStatus newStatus) {
        // 상태 변경 규칙 정의
        if (this == NEW && newStatus == PROCESSING) return true;
        if (this == PROCESSING && newStatus == SHIPPED) return true;
        if (this == SHIPPED && newStatus == DELIVERED) return true;
        return false;
    }
}

 

균열 인식과 해결 방법

  • 모델 검토: 정기적으로 모델을 검토하여, 일관성 문제를 조기에 발견하고 해결할 수 있다. 이는 도메인 전문가와 개발자가 협력하여 모델을 검토하는 과정이다.
  • 명확한 경계 정의: 컨텍스트 간의 경계를 명확히 정의하여, 모델 간의 상호작용에서 발생할 수 있는 문제를 줄일 수 있다. 이는 경계를 넘나드는 데이터와 연산을 최소화하는 것을 포함한다.
  • 유효성 검사: 모델의 상태 변경 시 유효성 검사를 통해 일관성을 유지할 수 있다. 이는 상태 변경 로직을 명확히 정의하고, 규칙을 준수하도록 하는 것이다.
  • 이벤트 주도 설계: 컨텍스트 간의 상호작용을 이벤트 기반으로 처리하여, 느슨한 결합을 유지하고 일관성을 보장할 수 있다. 이는 이벤트를 통해 상태 변경을 통지하고, 필요한 처리를 수행하는 방식이다.

Countinous Integration (지속적인 통합)

지속적인 통합(Continuous Integration)의 핵심 개념

  • 자주하는 통합: 개발자들은 자주, 그리고 가능한 한 매일 여러 번 소스 코드 저장소에 코드를 통합한다. 각 통합은 코드 변경 사항을 포함하며, 작은 단위로 이루어진다.
  • 자동화된 빌드: 코드가 통합될 때마다 자동으로 빌드 프로세스가 실행된다. 이는 코드 컴파일, 종속성 해결, 코드 패키징 등을 포함한다.
  • 자동화된 테스트: 빌드 프로세스의 일환으로, 자동화된 테스트가 실행됩니다. 이는 유닛 테스트(Unit Test), 통합 테스트(Integration Test), 기능 테스트(Functional Test) 등을 포함합니다. 테스트가 통과하지 못하면 빌드가 실패한다.
  • 피드백 제공: 빌드와 테스트 결과는 즉시 개발자에게 피드백으로 제공된다. 이를 통해 개발자는 코드 변경이 기존 기능에 미치는 영향을 빠르게 파악하고, 문제를 조기에 수정할 수 있다.
  • 지속적인 코드 품질 검사: 빌드 프로세스 중 코드 품질을 검사하는 도구를 사용하여 코드 스타일, 정적 분석, 보안 취약점 등을 점검한다.

지속적인 통합의 장점

  • 조기 오류 발견 및 수정: 통합 문제와 버그를 조기에 발견하고 수정하여, 대규모 통합에서 발생할 수 있는 복잡한 문제를 방지한다.
  • 개발 속도 향상: 자동화된 빌드와 테스트를 통해 개발 주기를 단축하고, 더 자주 배포할 수 있다.
  • 코드 품질 향상: 지속적인 코드 품질 검사를 통해 코드 품질을 유지하고 향상시킬 수 있다.
  • 팀 협업 개선: 코드 변경 사항을 자주 통합함으로써 팀 간의 협업을 촉진하고, 충돌을 줄일 수 있다.

지속적인 통합의 구현 예

  • 소스 코드 관리 시스템: Git, Subversion 등과 같은 소스 코드 관리 시스템을 사용하여 코드 변경 사항을 관리한다.
  • CI 서버: Jenkins, Travis CI, CircleCI, GitHub Actions 등과 같은 CI 서버를 사용하여 자동화된 빌드 및 테스트 프로세스를 설정한다.
  • 자동화된 빌드 도구: Maven, Gradle, Ant 등과 같은 빌드 도구를 사용하여 빌드 프로세스를 자동화한다.
  • 자동화된 테스트 프레임워크: JUnit, TestNG, NUnit 등과 같은 테스트 프레임워크를 사용하여 자동화된 테스트를 작성하고 실행한다.

지속적인 통합의 베스트 프랙티스

  • 작고 빈번한 커밋: 작은 단위로 자주 커밋하여 통합 주기를 짧게 유지한다. 이는 통합 문제를 조기에 발견하고 해결하는 데 도움이 된다.
  • 빠른 피드백 루프: 빌드와 테스트 프로세스를 가능한 한 빨리 실행하여 개발자에게 신속한 피드백을 제공한다.
  • 모든 커밋에 대한 빌드: 모든 커밋에 대해 빌드와 테스트를 실행하여, 코드 변경이 기존 기능에 미치는 영향을 즉시 확인한다.
  • 테스트 커버리지 확대: 가능한 한 많은 유닛 테스트와 통합 테스트를 작성하여 코드 변경의 영향을 충분히 테스트한다.
  • 빌드 결과 모니터링: 빌드 결과를 지속적으로 모니터링하고, 실패 시 즉시 대응한다.

Conext Map (컨텍스트 맵)

컨텍스트 맵(Context Map)이란?

  • 컨텍스트 맵은 여러 제한된 컨텍스트 간의 관계와 경계를 시각적으로 표현한 다이어그램
  • 이는 각 컨텍스트의 역할과 책임을 명확히 하고, 시스템 전반의 구조를 이해하는 데 도움을 준다

컨텍스트 경계에서의 테스트

  • 컨텍스트 경계에서의 테스트는 제한된 컨텍스트 간의 상호작용을 검증하는 테스트
  • 이는 통합 테스트와 유사하지만, 특히 도메인 모델의 일관성과 경계 간의 인터페이스를 강조한다.
  • 컨텍스트 간의 상호작용이 예상대로 동작하는지 검증하고, 경계 간의 통신이 올바르게 이루어지는지 확인하는 역할
  • 방법:
    • 계약 기반 테스트: 각 컨텍스트가 제공하는 서비스와 소비하는 서비스 간의 계약을 정의하고, 이를 검증한다. 이는 서비스 인터페이스와 데이터 형식을 포함한다.
    • 통합 테스트: 실제 환경에서 컨텍스트 간의 상호작용을 검증한다. 이는 실제 데이터베이스나 메시지 큐 등을 사용하여 테스트한다.
    • 모의 객체(Mock) 사용: 테스트 환경에서 다른 컨텍스트의 동작을 모의 객체로 대체하여 상호작용을 검증한다. 이는 테스트를 간소화하고, 독립성을 유지하는 데 도움이 된다.
    • 예제
public class OrderServiceTest {
    private OrderService orderService;
    private InventoryService mockInventoryService;

    @Before
    public void setUp() {
        mockInventoryService = mock(InventoryService.class);
        orderService = new OrderService(mockInventoryService);
    }

    @Test
    public void testPlaceOrderWithSufficientStock() {
        // Mock inventory service response
        when(mockInventoryService.checkStock(any(Product.class), anyInt())).thenReturn(true);

        Order order = new Order();
        order.addItem(new OrderItem(new Product("Product1"), 2));

        boolean result = orderService.placeOrder(order);

        assertTrue(result);
        verify(mockInventoryService, times(1)).checkStock(any(Product.class), anyInt());
    }
}

컨텍스트 맵의 조직화와 문서화

  • 조직화:
    • 컨텍스트 식별: 시스템 내의 주요 제한된 컨텍스트를 식별한다. 이는 각 컨텍스트가 담당하는 주요 도메인 기능을 정의한다.
    • 관계 정의: 컨텍스트 간의 관계를 정의한다. 이는 컨텍스트 간의 통합 방식(예: 고객-공급자(Customer-Supplier), 공통 커널(Shared Kernel), 파트너십(Partnership) 등)을 포함한다.
    • 경계 명확화: 각 컨텍스트의 경계를 명확히 하고, 경계 간의 데이터 흐름과 상호작용을 정의한다.
  • 문서화:
    • 다이어그램 사용: 제한된 컨텍스트와 그 관계를 시각적으로 표현하는 다이어그램을 작성한다. 이는 시스템 전반의 구조를 쉽게 이해할 수 있도록 돕는다.
    • 텍스트 설명: 다이어그램에 대한 자세한 설명을 포함한 문서를 작성한다. 이는 각 컨텍스트의 역할, 책임, 경계 및 상호작용에 대한 자세한 정보를 제공한다.
    • 통합 패턴 설명: 컨텍스트 간의 통합 방식과 통합 패턴(예: ACL, 공통 커널, 고객-공급자 등)을 설명한다.
  • 예제:
+--------------------+       +--------------------+
| Order Management   |       | Inventory Management|
|                    |       |                    |
| - Place Order      |<----->| - Check Stock      |
| - Cancel Order     |       | - Update Inventory |
+--------------------+       +--------------------+
  • 문서 예제:
## Order Management Context

### 책임
- 주문 생성, 수정, 취소 등의 주문 관리 기능을 담당합니다.

### 주요 기능
- 주문 생성 및 상태 관리
- 주문 취소

### 상호작용
- Inventory Management 컨텍스트와 통신하여 재고 확인 및 업데이트를 수행합니다.

## Inventory Management Context

### 책임
- 제품의 재고 관리 및 업데이트를 담당합니다.

### 주요 기능
- 재고 확인
- 재고 업데이트

### 상호작용
- Order Management 컨텍스트와 통신하여 주문 처리 시 재고를 확인하고 업데이트합니다.

Bounded Context 간의 관계

제한된 컨텍스트 간의 관계 유형

  • 공통 커널(Shared Kernel):
    • 두 개 이상의 제한된 컨텍스트가 공통의 하위 집합(커널)을 공유하는 관계
    • 이 커널은 공통으로 사용하는 모델을 포함하며, 모든 관련 컨텍스트에서 일관되게 유지되어야 한다.
    • 예제: 결제 시스템과 주문 시스템이 공통으로 사용하는 고객 정보 모델
  • 고객-공급자(Customer-Supplier):
    • 한 컨텍스트(공급자)가 다른 컨텍스트(고객)에게 서비스를 제공하는 관계
    • 고객은 공급자가 제공하는 서비스의 사양에 따라 자신의 요구를 조정한다.
    • 예제: 주문 시스템이 재고 시스템에게 재고 정보를 요청하는 경우, 주문 시스템이 고객이고 재고 시스템이 공급자가 된다.
  • 파트너십(Partnership):
    • 두 개의 제한된 컨텍스트가 긴밀하게 협력하여 공동의 목표를 달성하는 관계
    • 양쪽 컨텍스트는 상호 의존적이며, 협력의 성공 여부가 둘 다에게 중요하다.
    • 예제: 상품 카탈로그 시스템과 추천 시스템이 협력하여 사용자에게 맞춤형 추천을 제공하는 경우.
  • 단방향(one-way)와 양방향(two-way) 관계:
    • 단방향: 한 컨텍스트가 다른 컨텍스트에 종속되어 있는 관계로, 한 방향으로만 의존
      • 예제: 재고 시스템이 배송 시스템을 호출하여 배송 상태를 업데이트하는 경우.
    • 양방향: 두 개의 컨텍스트가 상호 종속되어 있는 관계로, 서로를 호출하거나 데이터를 주고받는다.
      • 예제: 주문 시스템과 고객 관리 시스템이 서로 데이터를 주고받는 경우.
  • 컨텍스트 매핑(Context Mapping):
    • 두 개 이상의 컨텍스트가 어떻게 데이터를 주고받고 상호작용하는지를 명확히 정의하는 작업
    • 이는 데이터의 흐름과 변환 과정을 명확히 함으로써 각 컨텍스트 간의 통합을 쉽게 만든다.

제한된 컨텍스트 간의 관계 예제

  • 예제 1: 공통 커널
+------------------------+            +----------------------+
|  Order Management      |            |  Payment Management  |
|                        |            |                      |
|  - Order Creation      |            |  - Payment Handling  |
|  - Order Tracking      |            |  - Payment Status    |
|                        |            |                      |
|  Shared Kernel         |<---------->|  Shared Kernel       |
|  - Customer Info       |            |  - Customer Info     |
+------------------------+            +----------------------+
  • 예제 2: 고객-공급자 관계
+------------------------+            +----------------------+
|  Order Management      |            |  Inventory Management|
|                        |            |                      |
|  - Place Order         |            |  - Check Stock       |
|  - Cancel Order        |            |  - Update Inventory  |
|                        |            |                      |
|  Customer              |<---------->|  Supplier            |
+------------------------+            +----------------------+

 

  • 예제 3: 파트너십 관계
+------------------------+            +----------------------+
|  Order Management      |            |  Inventory Management|
|                        |            |                      |
|  - Place Order         |            |  - Check Stock       |
|  - Cancel Order        |            |  - Update Inventory  |
|                        |            |                      |
|  Customer              |<---------->|  Supplier            |
+------------------------+            +----------------------+

Shared Kernel (공유 커널)

공유 커널(Shared Kernel) 정의

  • 공유 커널은 두 개 이상의 제한된 컨텍스트가 공통으로 사용하는 모델, 데이터, 또는 기능의 집합
  • 이 커널은 공유되는 부분의 일관성과 무결성을 유지하는 데 중점을 둔다.
  • 중복을 줄이고, 공유되는 데이터나 로직의 일관성을 유지함으로써 시스템의 복잡성을 관리한다.

공유 커널의 특징

  • 공유된 모델: 공유 커널은 여러 컨텍스트에서 공통으로 사용하는 도메인 모델을 포함한다. (예를 들어, 고객 정보, 제품 정보)
  • 일관성 유지: 공유 커널의 변경은 관련 모든 컨텍스트에 영향을 미친다. 따라서 일관성을 유지하기 위해 협력과 커뮤니케이션이 중요하다.
  • 긴밀한 협력: 공유 커널을 사용하는 컨텍스트 간에는 긴밀한 협력과 의사소통이 필요하다. 이는 변경 관리와 충돌 해결을 위해 필수적이다.

공유 커널의 장점

  • 중복 제거: 여러 컨텍스트에서 공통으로 사용하는 모델을 공유함으로써 중복을 제거할 수 있다. 이는 코드의 간결성과 유지보수성을 높인다.
  • 일관성 보장: 공유 커널을 통해 여러 컨텍스트 간에 일관된 데이터를 유지할 수 있다. 이는 데이터의 정확성과 신뢰성을 높인다.
  • 재사용성 향상: 공통 기능이나 모델을 재사용함으로써 개발 시간을 단축하고, 시스템의 일관성을 유지할 수 있다.

공유 커널의 단점

  • 변경 관리의 어려움: 공유된 부분의 변경은 관련 모든 컨텍스트에 영향을 미치므로, 변경 관리가 어렵고 복잡할 수 있다.
  • 높은 결합도: 공유 커널을 사용하는 컨텍스트 간의 결합도가 높아질 수 있다. 이는 한 컨텍스트의 변화가 다른 컨텍스트에 영향을 미칠 수 있음을 의미한다.
  • 조정과 협력 필요: 공유 커널을 효과적으로 사용하려면 관련 팀 간의 긴밀한 협력과 조정이 필요하다. 이는 커뮤니케이션 비용을 증가시킬 수 있다.

공유 커널 예제

  • 예제 1: 온라인 쇼핑몰
  • 컨텍스트: 주문 관리(Order Management)와 결제 관리(Payment Management)
    • 공유 커널: 고객 정보(Customer Information)
    • 주문 관리와 결제 관리 컨텍스트는 고객 정보를 공유 커널로 사용한다.
    • 이는 두 컨텍스트가 고객 정보를 일관되게 사용하도록 보장한다.
+------------------------+            +----------------------+
|  Order Management      |            |  Payment Management  |
|                        |            |                      |
|  - Place Order         |            |  - Process Payment   |
|  - Cancel Order        |            |  - Refund Payment    |
|                        |            |                      |
|  Shared Kernel         |<---------->|  Shared Kernel       |
|  - Customer Info       |            |  - Customer Info     |
+------------------------+            +----------------------+
  • 코드 예제: Java
// Shared Kernel: Customer
public class Customer {
    private String customerId;
    private String name;
    private String email;

    // Constructors, getters, and setters
}

// Order Management Context
public class Order {
    private String orderId;
    private Customer customer; // Shared Kernel
    private List<OrderItem> items;

    // Constructors, getters, and setters
}

// Payment Management Context
public class Payment {
    private String paymentId;
    private Customer customer; // Shared Kernel
    private BigDecimal amount;

    // Constructors, getters, and setters
}

Customer/Supplier Development Teams (고객/공급자 개발 팀)

고객/공급자 개발 팀(Customer/Supplier Development Teams) 정의

  • 고객/공급자 개발 팀 모델은 하나의 개발 팀(고객)이 다른 개발 팀(공급자)에게 특정 서비스를 요청하고, 공급자 팀이 그 서비스를 제공하는 관계
  • 고객 팀은 공급자 팀이 제공하는 서비스의 요구사항을 정의하고, 공급자 팀은 그 요구사항을 충족시키기 위해 노력한다.

고객/공급자 관계의 특징

  • 명확한 요구사항: 고객 팀은 자신의 요구사항을 명확히 정의하고, 공급자 팀에게 전달한다. 이는 서비스의 기대치를 명확히 하고, 오해를 줄이는 데 중요하다.
  • 협력과 의사소통: 두 팀 간의 긴밀한 협력과 의사소통이 필수적이다. 정기적인 회의와 피드백 세션을 통해 요구사항과 제공되는 서비스의 품질을 조정한다.
  • 서비스 수준 협약(SLA): 서비스의 기대치와 품질을 보장하기 위해 서비스 수준 협약(SLA)을 정의할 수 있다. 이는 서비스의 가용성, 성능, 응답 시간 등의 지표를 포함할 수 있다.
  • 독립성과 상호 의존성: 고객 팀과 공급자 팀은 각각 독립적으로 동작하면서도, 상호 의존성을 인식하고 이를 관리할 수 있다. 이는 각 팀의 독립성을 유지하면서도, 협력의 필요성을 강조한다.

예제: 온라인 쇼핑몰에서의 고객/공급자 관계

  • 컨텍스트: 주문 관리(Order Management)와 재고 관리(Inventory Management)
    • 고객 팀: 주문 관리 팀
    • 공급자 팀: 재고 관리 팀
      • 주문 관리 팀은 주문을 처리하기 위해 재고 정보를 필요로 한다.
      • 따라서 재고 관리 팀에게 재고 확인과 업데이트 서비스를 요청한다.
+------------------------+            +------------------------+
|  Order Management Team |            |  Inventory Management  |
|                        |            |          Team          |
|  - Place Order         |            |  - Check Stock         |
|  - Cancel Order        |            |  - Update Inventory    |
|                        |            |                        |
|  Customer              |<---------->|  Supplier              |
+------------------------+            +------------------------+
  • 코드 예제: Java
    • 재고 관리 서비스(공급자):
public class InventoryService {
    public boolean checkStock(Product product, int quantity) {
        // 재고 확인 로직
        // ...
        return true; // 예제용
    }

    public void updateStock(Product product, int quantity) {
        // 재고 업데이트 로직
        // ...
    }
}

 

  • 주문 관리 서비스(고객):
public class OrderService {
    private final InventoryService inventoryService;

    public OrderService(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    public boolean placeOrder(Order order) {
        for (OrderItem item : order.getItems()) {
            if (!inventoryService.checkStock(item.getProduct(), item.getQuantity())) {
                return false; // 재고 부족으로 주문 실패
            }
        }
        for (OrderItem item : order.getItems()) {
            inventoryService.updateStock(item.getProduct(), item.getQuantity());
        }
        // 주문 처리 로직
        // ...
        return true;
    }

    public void cancelOrder(Order order) {
        for (OrderItem item : order.getItems()) {
            inventoryService.updateStock(item.getProduct(), -item.getQuantity());
        }
        // 주문 취소 로직
        // ...
    }
}

Conformist (준수자)

준수자(Conformist) 정의

  • 준수자 패턴은 하나의 컨텍스트(준수자)가 다른 컨텍스트(주도자)의 모델이나 서비스에 맞춰 자신의 모델이나 구현을 조정하는 관계를 의미한다.
  • 준수자는 주도자가 결정한 모델이나 인터페이스를 그대로 따른다.

준수자의 특징

  • 의존성: 준수자는 주도자 컨텍스트에 강하게 의존한다. 이는 주도자가 정의한 모델이나 인터페이스의 변경이 준수자에게 직접적인 영향을 미친다는 것을 의미한다.
  • 일관성 유지: 준수자는 주도자의 표준을 따름으로써 시스템 전반의 일관성을 유지한다. 이는 통합 과정에서 발생할 수 있는 충돌을 최소화한다.
  • 비대칭적 관계: 주도자와 준수자 간의 관계는 비대칭적이다. 주도자는 모델이나 인터페이스를 정의하고 변경할 수 있는 권한을 가지지만, 준수자는 이를 따른다.

준수자 예제

  • 예제: 결제 시스템과 청구 시스템
  • 컨텍스트: 결제 처리(Payment Processing)와 청구 관리(Billing Management)
    • 주도자: 결제 처리 시스템
    • 준수자: 청구 관리 시스템
      • 결제 처리 시스템이 주도자로서 결제 모델과 인터페이스를 정의하고, 청구 관리 시스템은 이 모델과 인터페이스를 준수하여 자신의 모델을 조정한다.
+------------------------+            +----------------------+
|  Payment Processing    |            |  Billing Management  |
|                        |            |                      |
|  - Process Payment     |            |  - Generate Invoice  |
|  - Update Payment Status|           |  - Track Payments    |
|                        |            |                      |
|  Leader                |<---------->|  Conformist          |
+------------------------+            +----------------------+
  • 코드 예제: Java
    • 결제 처리 시스템(주도자):
public class Payment {
    private String paymentId;
    private BigDecimal amount;
    private String status;

    // Constructors, getters, and setters
}

public class PaymentService {
    public Payment processPayment(String paymentId, BigDecimal amount) {
        // 결제 처리 로직
        Payment payment = new Payment(paymentId, amount, "Processed");
        return payment;
    }

    public void updatePaymentStatus(String paymentId, String status) {
        // 결제 상태 업데이트 로직
    }
}
  • 청구 관리 시스템(준수자):
public class Invoice {
    private String invoiceId;
    private String paymentId;
    private BigDecimal amount;
    private String status;

    // Constructors, getters, and setters
}

public class BillingService {
    private PaymentService paymentService;

    public BillingService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public Invoice generateInvoice(String paymentId, BigDecimal amount) {
        Payment payment = paymentService.processPayment(paymentId, amount);
        return new Invoice(UUID.randomUUID().toString(), payment.getPaymentId(), payment.getAmount(), payment.getStatus());
    }

    public void trackPayment(String paymentId) {
        // 청구 관리 로직
    }
}

Anti-corruption Layer (오류 방지 계층)

오류 방지 계층(Anti-Corruption Layer, ACL) 정의

  • 오류 방지 계층(ACL)은 도메인 모델과 외부 시스템 간의 변환 및 통신을 관리하는 계층
  • 이 계층은 외부 시스템의 데이터와 도메인 모델 간의 매핑, 변환, 검증 등을 담당한다.
  • 목적:
    • 도메인 모델을 외부 시스템의 복잡성이나 불일치로부터 보호하고, 도메인 모델의 일관성과 무결성을 유지한다.
    • 외부 시스템의 변경이 도메인 모델에 직접적인 영향을 미치지 않도록 하여, 도메인 모델의 안정성을 높인다.

오류 방지 계층의 특징

  • 데이터 변환 및 매핑:외부 시스템의 데이터 형식을 도메인 모델의 형식으로 변환하거나, 그 반대로 변환하는 역할을 한다. 이를 통해 두 시스템 간의 데이터 불일치를 해결한다.
  • 독립성 유지: 도메인 모델이 외부 시스템의 복잡성에 직접 노출되지 않도록 하여, 도메인 모델의 독립성을 유지한다.
  • 변경 관리: 외부 시스템의 변경이 도메인 모델에 직접적인 영향을 미치지 않도록 한다. 외부 시스템이 변경되면 ACL을 수정하여 변경 사항을 처리한다.
  • 보안 및 검증: 외부 시스템에서 들어오는 데이터의 유효성을 검증하고, 필요한 보안 조치를 수행한다.

오류 방지 계층의 장점

  • 도메인 모델 보호: 도메인 모델을 외부 시스템의 복잡성이나 불일치로부터 보호하여, 도메인 모델의 일관성과 무결성을 유지한다.
  • 유연성 향상: 외부 시스템의 변경이 ACL을 통해 관리되므로, 도메인 모델의 변경 없이 외부 시스템과의 통합을 유연하게 처리할 수 있다.
  • 코드 가독성 및 유지보수성: 도메인 모델과 외부 시스템 간의 상호작용이 ACL에 캡슐화되므로, 코드의 가독성과 유지보수성이 향상된다.

오류 방지 계층의 인터페이스 설계

  • 명확한 역할 분리: ACL의 인터페이스는 도메인 모델과 외부 시스템 간의 역할을 명확히 분리해야 한다. 각 인터페이스는 특정 기능을 담당하도록 설계한다.
  • 데이터 변환 책임: 인터페이스는 외부 시스템의 데이터를 도메인 모델로 변환하거나 그 반대의 역할을 수행해야 한다. 이 변환 로직은 ACL 내부에 캡슐화되어야 한다.
  • 유효성 검사 및 예외 처리: 외부 시스템에서 들어오는 데이터의 유효성을 검사하고, 필요한 경우 예외를 처리하여 도메인 모델이 잘못된 데이터에 의해 손상되지 않도록 한다.
  • 의미 있는 메서드 명명: 인터페이스의 메서드 이름은 그 역할과 목적을 명확히 나타내야 한다. 이는 코드의 가독성과 유지보수성을 높이는 데 중요하다.

 

코드 예제: Java

  • 외부 시스템 API (LegacySystem)
public class LegacySystem {
    public String fetchCustomerData(String customerId) {
        // 외부 시스템에서 고객 데이터를 가져오는 로직
        return "{ \"id\": \"" + customerId + "\", \"name\": \"John Doe\", \"age\": 30 }";
    }

    public boolean saveOrderData(String orderJson) {
        // 외부 시스템에 주문 데이터를 저장하는 로직
        return true;
    }
}
  • 도메인 모델 (Customer, Order)
public class Customer {
    private String id;
    private String name;
    private int age;

    // Constructors, getters, and setters
}

public class Order {
    private String id;
    private String customerId;
    private List<OrderItem> items;

    // Constructors, getters, and setters
}

public class OrderItem {
    private String productId;
    private int quantity;

    // Constructors, getters, and setters
}
  • 오류 방지 계층 (ACL)
public interface CustomerRepository {
    Customer findCustomerById(String customerId);
}

public interface OrderRepository {
    boolean saveOrder(Order order);
}

public class AntiCorruptionLayer implements CustomerRepository, OrderRepository {
    private final LegacySystem legacySystem;

    public AntiCorruptionLayer(LegacySystem legacySystem) {
        this.legacySystem = legacySystem;
    }

    @Override
    public Customer findCustomerById(String customerId) {
        String customerData = legacySystem.fetchCustomerData(customerId);
        // JSON 데이터를 Customer 객체로 변환
        // (여기서는 간단히 예를 위해 직접 변환합니다)
        JSONObject json = new JSONObject(customerData);
        return new Customer(json.getString("id"), json.getString("name"), json.getInt("age"));
    }

    @Override
    public boolean saveOrder(Order order) {
        // Order 객체를 JSON 형식으로 변환
        // (여기서는 간단히 예를 위해 직접 변환합니다)
        JSONObject json = new JSONObject();
        json.put("id", order.getId());
        json.put("customerId", order.getCustomerId());
        JSONArray itemsArray = new JSONArray();
        for (OrderItem item : order.getItems()) {
            JSONObject itemJson = new JSONObject();
            itemJson.put("productId", item.getProductId());
            itemJson.put("quantity", item.getQuantity());
            itemsArray.put(itemJson);
        }
        json.put("items", itemsArray);
        return legacySystem.saveOrderData(json.toString());
    }
}

Separate Ways (각자의 길)

각자의 길(Separate Ways) 패턴 정의

  • 각자의 길 패턴은 두 개 이상의 제한된 컨텍스트가 서로 독립적으로 존재하고, 상호작용을 최소화하는 관계를 의미한다.
  • 각 컨텍스트는 자신의 데이터와 비즈니스 로직을 독립적으로 관리한다.
  • 목적:
    • 제한된 컨텍스트 간의 결합도를 낮추고, 독립성을 유지하여 시스템의 복잡성을 관리하고 유연성을 높인다.

각자의 길 패턴의 특징

  • 독립성: 각 컨텍스트는 자신의 데이터와 비즈니스 로직을 독립적으로 관리한다. 이는 컨텍스트 간의 결합도를 낮추고, 독립적으로 발전할 수 있도록 한다.
  • 상호작용 최소화: 컨텍스트 간의 상호작용을 최소화하여, 변경 사항이 다른 컨텍스트에 미치는 영향을 줄인다.
  • 중복 허용: 동일한 개념이나 데이터를 각 컨텍스트가 독립적으로 관리할 수 있으므로, 중복이 허용된다. 이는 각 컨텍스트가 자신의 요구사항에 맞게 데이터를 최적화할 수 있도록 한다.

 

예제: 온라인 쇼핑몰

  • 컨텍스트: 주문 관리(Order Management)와 고객 관리(Customer Management)
  • 주문 관리: 주문 생성, 주문 상태 변경, 주문 이력 관리 등.
  • 고객 관리: 고객 정보 관리, 고객 인증, 고객 서비스 등.
    • 주문 관리와 고객 관리 컨텍스트는 서로 독립적으로 동작하며, 필요한 경우에만 데이터를 공유한다. 각 컨텍스트는 자신의 데이터를 독립적으로 관리한다.
+------------------------+            +----------------------+
|  Order Management      |            |  Customer Management |
|                        |            |                      |
|  - Place Order         |            |  - Add Customer      |
|  - Cancel Order        |            |  - Update Customer   |
|                        |            |                      |
|  Separate Ways         |            |  Separate Ways       |
+------------------------+            +----------------------+
  • 코드 예제: Java
    • 주문 관리 컨텍스트:
public class Order {
    private String orderId;
    private String customerId;
    private List<OrderItem> items;
    private OrderStatus status;

    // Constructors, getters, and setters
}

public class OrderService {
    public Order placeOrder(String customerId, List<OrderItem> items) {
        // 주문 생성 로직
        Order order = new Order(UUID.randomUUID().toString(), customerId, items, OrderStatus.NEW);
        // 주문 저장 로직
        return order;
    }

    public void cancelOrder(String orderId) {
        // 주문 취소 로직
    }
}
  • 고객 관리 컨텍스트:
public class Customer {
    private String customerId;
    private String name;
    private String email;

    // Constructors, getters, and setters
}

public class CustomerService {
    public Customer addCustomer(String name, String email) {
        // 고객 추가 로직
        Customer customer = new Customer(UUID.randomUUID().toString(), name, email);
        // 고객 저장 로직
        return customer;
    }

    public void updateCustomer(String customerId, String name, String email) {
        // 고객 정보 업데이트 로직
    }
}

Open Host Service(공개 호스트 서비스) - 표준화된 서비스 형식

공개 호스트 서비스(Open Host Service) 정의

  • 공개 호스트 서비스는 여러 제한된 컨텍스트 또는 시스템 간의 통합을 위해 공통된 언어와 인터페이스를 정의하는 패턴이다.
  • 이 언어와 인터페이스는 모든 통합 참여자들이 이해하고 준수해야 하는 표준을 제공한다.
  • 목적:
    • 통합되는 시스템 간의 상호작용을 일관성 있게 만들고, 각 시스템이 독립적으로 발전할 수 있도록 한다.
    • 데이터 형식, 통신 프로토콜, API 계약 등을 명확히 정의하여 시스템 간의 통합을 단순화하고, 오류를 줄인다.

공개 호스트 서비스의 특징

  • 공통 언어 정의: 여러 시스템 또는 컨텍스트가 이해하고 사용할 수 있는 공통된 언어를 정의한다. 이는 데이터 구조, API 계약, 메시지 형식 등을 포함한다.
  • 명확한 계약: 시스템 간의 상호작용을 위한 명확한 계약을 정의한다. 이는 API 문서, 데이터 스키마, 통신 프로토콜 등의 형태로 제공된다.
  • 일관성 유지: 모든 통합 참여자들이 공통 언어와 계약을 준수하도록 하여, 시스템 간의 일관성을 유지한다.
  • 독립적 발전: 각 시스템은 공통 계약을 준수하는 한, 독립적으로 발전할 수 있다. 이는 각 시스템이 자신의 도메인 논리에 집중하고, 변경 사항이 다른 시스템에 미치는 영향을 최소화할 수 있도록 한다.

예제: 온라인 쇼핑몰과 결제 시스템 통합

  • 컨텍스트: 온라인 쇼핑몰(Order Management)과 결제 처리(Payment Processing)
  • 온라인 쇼핑몰: 주문 생성, 주문 상태 변경, 주문 이력 관리 등
  • 결제 처리: 결제 승인, 결제 상태 변경, 결제 기록 관리 등.
    • 온라인 쇼핑몰과 결제 시스템 간의 통합을 위해 공통된 언어와 계약을 정의한다. 이는 주문 생성 시 결제 승인 요청, 결제 완료 시 주문 상태 변경 등의 작업을 포함한다.
+------------------------+            +----------------------+
|  Order Management      |            |  Payment Processing  |
|                        |            |                      |
|  - Place Order         |            |  - Authorize Payment |
|  - Cancel Order        |            |  - Capture Payment   |
|                        |            |                      |
|  Published Language    |<---------->|  Published Language  |
+------------------------+            +----------------------+
  • 코드 예제: Java
    • 공개 호스트 서비스 계약 (Published Language Contract):
// Payment Request DTO
public class PaymentRequest {
    private String orderId;
    private BigDecimal amount;
    private String currency;

    // Constructors, getters, and setters
}

// Payment Response DTO
public class PaymentResponse {
    private String transactionId;
    private String status;

    // Constructors, getters, and setters
}
  • 결제 처리 시스템 (Payment Processing System):
public class PaymentService {
    public PaymentResponse authorizePayment(PaymentRequest request) {
        // 결제 승인 로직
        PaymentResponse response = new PaymentResponse(UUID.randomUUID().toString(), "AUTHORIZED");
        return response;
    }

    public PaymentResponse capturePayment(String transactionId) {
        // 결제 완료 로직
        PaymentResponse response = new PaymentResponse(transactionId, "CAPTURED");
        return response;
    }
}
  • 온라인 쇼핑몰 시스템 (Order Management System):
public class OrderService {
    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void placeOrder(Order order) {
        // 주문 생성 로직
        PaymentRequest paymentRequest = new PaymentRequest(order.getOrderId(), order.getTotalAmount(), "USD");
        PaymentResponse paymentResponse = paymentService.authorizePayment(paymentRequest);

        if ("AUTHORIZED".equals(paymentResponse.getStatus())) {
            // 주문 상태를 '결제 승인'으로 변경
            order.setStatus(OrderStatus.AUTHORIZED);
        } else {
            // 결제 실패 처리
            order.setStatus(OrderStatus.FAILED);
        }
    }
}

Published Language (공표된 언어) - 표준화된 데이터 형식

공표된 언어(Published Language) 정의

  • 공표된 언어는 여러 제한된 컨텍스트 또는 시스템 간의 통합을 위해 공통된 언어, 데이터 형식, 프로토콜, API 등을 정의하는 패턴이다.
  • 이를 통해 통합 참여자들이 이해하고 사용할 수 있는 표준을 제공한다.
  • 목적:
    • 시스템 간의 상호작용을 일관성 있게 만들고, 각 시스템이 독립적으로 발전할 수 있도록 한다.
    • 데이터 형식, 통신 프로토콜, API 계약 등을 명확히 정의하여 시스템 간의 통합을 단순화하고, 오류를 줄인다.

공표된 언어의 특징

  • 공통 언어 정의: 여러 시스템 또는 컨텍스트가 이해하고 사용할 수 있는 공통된 언어를 정의한다. 이는 데이터 구조, API 계약, 메시지 형식 등을 포함한다.
  • 명확한 계약: 시스템 간의 상호작용을 위한 명확한 계약을 정의한다. 이는 API 문서, 데이터 스키마, 통신 프로토콜 등의 형태로 제공된다.
  • 일관성 유지: 모든 통합 참여자들이 공통 언어와 계약을 준수하도록 하여, 시스템 간의 일관성을 유지한다.
  • 독립적 발전: 각 시스템은 공통 계약을 준수하는 한, 독립적으로 발전할 수 있다. 이는 각 시스템이 자신의 도메인 논리에 집중하고, 변경 사항이 다른 시스템에 미치는 영향을 최소화할 수 있도록 한다.

예제: 온라인 쇼핑몰과 결제 시스템 통합

  • 컨텍스트: 온라인 쇼핑몰(Order Management)과 결제 처리(Payment Processing)
  • 온라인 쇼핑몰: 주문 생성, 주문 상태 변경, 주문 이력 관리 등.
  • 결제 처리: 결제 승인, 결제 상태 변경, 결제 기록 관리 등.
    • 온라인 쇼핑몰과 결제 시스템 간의 통합을 위해 공통된 언어와 계약을 정의한다. 이는 주문 생성 시 결제 승인 요청, 결제 완료 시 주문 상태 변경 등의 작업을 포함한다.
+------------------------+            +----------------------+
|  Order Management      |            |  Payment Processing  |
|                        |            |                      |
|  - Place Order         |            |  - Authorize Payment |
|  - Cancel Order        |            |  - Capture Payment   |
|                        |            |                      |
|  Published Language    |<---------->|  Published Language  |
+------------------------+            +----------------------+

 

반응형
LIST

'도서' 카테고리의 다른 글

DDD - 에릭 에반스, (16장 대규모 구조)  (0) 2024.06.29
DDD - 에릭 에반스, (15장 디스틸레이션)  (0) 2024.06.29
DDD - 에릭 에반스, (11장 모델과 디자인 패턴의 연결)  (0) 2024.06.29
DDD - 에릭 에반스, (11장 분석 패턴의 적용)  (0) 2024.06.29
DDD - 에릭 에반스, (10장 유연한 설계)  (0) 2024.06.29
  1. Bounded Context (제한된 컨텍스트)
  2. 제한된 컨텍스트(Bounded Context)
  3. 제한된 컨텍스트의 장점
  4. 제한된 컨텍스트 안의 균열 인식
  5. 예제
  6. 균열 인식과 해결 방법
  7. Countinous Integration (지속적인 통합)
  8. 지속적인 통합(Continuous Integration)의 핵심 개념
  9. 지속적인 통합의 장점
  10. 지속적인 통합의 구현 예
  11. 지속적인 통합의 베스트 프랙티스
  12. Conext Map (컨텍스트 맵)
  13. 컨텍스트 맵(Context Map)이란?
  14. 컨텍스트 경계에서의 테스트
  15. 컨텍스트 맵의 조직화와 문서화
  16. Bounded Context 간의 관계
  17. 제한된 컨텍스트 간의 관계 유형
  18. 제한된 컨텍스트 간의 관계 예제
  19. Shared Kernel (공유 커널)
  20. 공유 커널(Shared Kernel) 정의
  21. 공유 커널의 특징
  22. 공유 커널의 장점
  23. 공유 커널의 단점
  24. 공유 커널 예제
  25. Customer/Supplier Development Teams (고객/공급자 개발 팀)
  26. 고객/공급자 개발 팀(Customer/Supplier Development Teams) 정의
  27. 고객/공급자 관계의 특징
  28. 예제: 온라인 쇼핑몰에서의 고객/공급자 관계
  29. Conformist (준수자)
  30. 준수자(Conformist) 정의
  31. 준수자의 특징
  32. 준수자 예제
  33. Anti-corruption Layer (오류 방지 계층)
  34. 오류 방지 계층(Anti-Corruption Layer, ACL) 정의
  35. 오류 방지 계층의 특징
  36. 오류 방지 계층의 장점
  37. 오류 방지 계층의 인터페이스 설계
  38. 코드 예제: Java
  39. Separate Ways (각자의 길)
  40. 각자의 길(Separate Ways) 패턴 정의
  41. 각자의 길 패턴의 특징
  42. 예제: 온라인 쇼핑몰
  43. Open Host Service(공개 호스트 서비스) - 표준화된 서비스 형식
  44. 공개 호스트 서비스(Open Host Service) 정의
  45. 공개 호스트 서비스의 특징
  46. 예제: 온라인 쇼핑몰과 결제 시스템 통합
  47. Published Language (공표된 언어) - 표준화된 데이터 형식
  48. 공표된 언어(Published Language) 정의
  49. 공표된 언어의 특징
  50. 예제: 온라인 쇼핑몰과 결제 시스템 통합
'도서' 카테고리의 다른 글
  • DDD - 에릭 에반스, (16장 대규모 구조)
  • DDD - 에릭 에반스, (15장 디스틸레이션)
  • DDD - 에릭 에반스, (11장 모델과 디자인 패턴의 연결)
  • DDD - 에릭 에반스, (11장 분석 패턴의 적용)
iron_jin
iron_jin
배운 것에 대한 내 생각을 가지고 정리하자
學而不思則罔(학이불사즉망)배운 것에 대한 내 생각을 가지고 정리하자
iron_jin
學而不思則罔(학이불사즉망)
iron_jin
전체
오늘
어제
  • 전체 (163)
    • 도서 (10)
    • 생각 정리 (0)
    • 후기 모음 (14)
    • 언어 (20)
      • css (1)
      • java (9)
      • Kotlin (0)
      • javascript (0)
      • Solidity (3)
      • Python (3)
      • GO (3)
      • C++ (1)
    • Spring Framework (32)
      • spring (16)
      • JPA (6)
      • Error (4)
      • Settings (4)
    • 알고리즘 (62)
      • 이론 (0)
      • 연습문제 (58)
    • 인프라 (6)
      • 클라우드 (1)
      • 도커 (0)
      • AWS (4)
      • Elastic Search (0)
    • 쿠버네티스 (3)
      • 이론 (0)
      • 실습 (2)
      • 트러블슈팅 (1)
    • Nginx (2)
    • CS (4)
      • 서버 (0)
      • 리눅스 (2)
      • 네트워크 (0)
      • OAuth (2)
    • 형상관리 (3)
      • GIT (3)
    • Open API (3)
      • 카카오 API (1)
      • QGIS (2)
    • 보안 (0)
      • 알고리즘 (0)
    • 공통 (1)
      • 성능 관리 도구 (1)
    • Database (2)
      • MySQL (1)
      • Redis (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 2019 카카오
  • 스프링 부트
  • 2019 카카오 블라인드
  • 자바
  • spring
  • ddd
  • 에릭 에반스
  • 2020 카카오
  • 2018 카카오 블라인드
  • spring boot
  • 알고리즘
  • 도메인 주도 개발
  • 2020 카카오 블라인드
  • 2018 kakao
  • 스프링
  • 항해99
  • 프로그래머스
  • JPA
  • AWS
  • 2019 kakao
  • Python
  • Java
  • Hibernate
  • 카카오 겨울 인턴십
  • 항해플러스
  • 2020 kakao
  • SpringBoot
  • 백준
  • MySQL
  • 코딩테스트

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
iron_jin
DDD - 에릭 에반스, (14장 모델의 무결성 유지)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.