예시: 주문 어그리게이트
public class Order {
private OrderId id;
private CustomerId customerId;
private List<OrderLine> orderLines;
private Money totalAmount;
public void addOrderLine(Product product, int quantity) {
OrderLine newLine = new OrderLine(product, quantity);
orderLines.add(newLine);
recalculateTotalAmount();
}
private void recalculateTotalAmount() {
this.totalAmount = orderLines.stream()
.map(OrderLine::getLineTotal)
.reduce(Money.ZERO, Money::add);
}
// 불변식 검증
public boolean isValid() {
return totalAmount.equals(
orderLines.stream()
.map(OrderLine::getLineTotal)
.reduce(Money.ZERO, Money::add)
);
}
}
이 예시에서 Order
는 어그리게이트 루트이며, OrderLine
들과 함께 하나의 어그리게이트를 형성합니다. addOrderLine
메서드는 새로운 주문 항목을 추가하고 총액을 재계산하는 작업을 원자적으로 수행합니다.
이벤추얼 컨시스턴시: 유연한 일관성 모델
이벤추얼 컨시스턴시는 분산 시스템에서 데이터의 일관성을 유지하는 방법으로, "결과적으로는 일관성이 보장된다"는 개념입니다.
이벤추얼 컨시스턴시의 특징:
- 비동기 업데이트: 변경사항이 시스템 전체에 즉시 반영되지 않아도 됩니다.
- 높은 가용성: 일시적인 불일치를 허용하므로 시스템의 가용성이 향상됩니다.
- 확장성: 서비스 간 강한 결합이 없어 독립적인 확장이 가능합니다.
예시: 주문과 재고 관리
// 주문 서비스
public class OrderService {
public void placeOrder(Order order) {
// 주문 처리 로직
orderRepository.save(order);
eventPublisher.publish(new OrderPlacedEvent(order));
}
}
// 재고 서비스
public class InventoryService {
@EventListener
public void onOrderPlaced(OrderPlacedEvent event) {
Order order = event.getOrder();
for (OrderLine line : order.getOrderLines()) {
Product product = line.getProduct();
int quantity = line.getQuantity();
inventoryRepository.decreaseStock(product.getId(), quantity);
}
}
}
이 예시에서 주문 처리와 재고 감소는 별도의 서비스에서 비동기적으로 처리됩니다. 주문이 생성되면 이벤트가 발행되고, 재고 서비스는 이 이벤트를 구독하여 재고를 업데이트합니다.