아래에서는 어그리게이트 방식과 각각 도메인 분리 방식의 구조를 그래프와 코드로 설명하겠습니다. 두 가지 접근 방식 모두 각각의 장단점이 있으므로, 시스템의 요구 사항에 따라 적절히 선택할 수 있습니다.

1. 어그리게이트 방식

구조 그래프

+---------------------------+
|      OrderAggregate       |  <--- 어그리게이트 루트
|  +---------------------+  |
|  |      Order          |  |  <--- 도메인 객체 (Order)
|  |  ID: 1              |  |
|  |  Status: Created    |  |
|  |  Total: 100.00      |  |
|  |                     |  |
|  |  +----------------+ |  |
|  |  |  OrderItem     | |  |  <--- 하위 도메인 객체 (OrderItem)
|  |  |  ID: 101       | |  |
|  |  |  Product: A    | |  |
|  |  |  Price: 50.00  | |  |
|  |  +----------------+ |  |
|  |  +----------------+ |  |
|  |  |  OrderItem     | |  |
|  |  |  ID: 102       | |  |
|  |  |  Product: B    | |  |
|  |  |  Price: 50.00  | |  |
|  |  +----------------+ |  |
|  +---------------------+  |
+---------------------------+

코드

도메인 계층

// 도메인 객체: OrderItem
public class OrderItem {
    private Long id;
    private String product;
    private BigDecimal price;

    public OrderItem(Long id, String product, BigDecimal price) {
        this.id = id;
        this.product = product;
        this.price = price;
    }

    // Getter 및 비즈니스 로직 메서드
}

// 어그리게이트 루트: Order
public class Order {
    private Long id;
    private String status;
    private BigDecimal totalAmount;
    private List<OrderItem> items = new ArrayList<>();

    public Order(Long id, String status) {
        this.id = id;
        this.status = status;
    }

    public void addItem(OrderItem item) {
        items.add(item);
        totalAmount = totalAmount.add(item.getPrice());
    }

    public void changeStatus(String newStatus) {
        this.status = newStatus;
    }

    // Getter 및 비즈니스 로직 메서드
}

JPA 엔티티

@Entity
public class OrderEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String status;
    private BigDecimal totalAmount;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "order_id")
    private List<OrderItemEntity> items;

    // 생성자, Getter 및 Setter
}

@Entity
public class OrderItemEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String product;
    private BigDecimal price;

    // 생성자, Getter 및 Setter
}

어댑터와 포트 인터페이스

// OrderPersistencePort 인터페이스
public interface OrderPersistencePort {
    void saveOrder(Order order);
    Order findOrderById(Long id);
}

// OrderAdapter 클래스
public class OrderAdapter implements OrderPersistencePort {
    private final OrderRepository orderRepository;

    public OrderAdapter(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @Override
    public void saveOrder(Order order) {
        List<OrderItemEntity> itemEntities = order.getItems().stream()
            .map(item -> new OrderItemEntity(item.getId(), item.getProduct(), item.getPrice()))
            .collect(Collectors.toList());

        OrderEntity orderEntity = new OrderEntity(order.getId(), order.getStatus(), order.getTotalAmount());
        orderEntity.setItems(itemEntities);
        orderRepository.save(orderEntity);
    }

    @Override
    public Order findOrderById(Long id) {
        return orderRepository.findById(id)
            .map(entity -> {
                Order order = new Order(entity.getId(), entity.getStatus());
                entity.getItems().forEach(itemEntity ->
                    order.addItem(new OrderItem(itemEntity.getId(), itemEntity.getProduct(), itemEntity.getPrice()))
                );
                return order;
            }).orElse(null);
    }
}

어그리게이트 방식 설명

2. 각각 도메인 분리 방식

구조 그래프

+---------------------------+
|         Order             |  <--- 도메인 객체
|  ID: 1                    |
|  Status: Created          |
|  Total: 100.00            |
+---------------------------+

+---------------------------+
|        OrderItem          |  <--- 독립적인 도메인 객체
|  ID: 101                  |
|  Product: A               |
|  Price: 50.00             |
+---------------------------+

+---------------------------+
|        OrderItem          |  <--- 독립적인 도메인 객체
|  ID: 102                  |
|  Product: B               |
|  Price: 50.00             |
+---------------------------+

코드

Order 도메인 객체