반응형
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 |