IT개발

도메인 주도 설계(DDD)에서 애그리거트 설계 팁과 헥사고날 아키텍처

우리모두 개발자되기 2025. 4. 27. 19:53

 

도메인 주도 설계(DDD)에서 애그리거트 설계 팁과 헥사고날 아키텍처

**도메인 주도 설계(DDD)**는 복잡한 비즈니스 문제를 해결하기 위해 소프트웨어 모델링에 비즈니스 도메인 전문가의 지식을 적극 반영하는 방법론입니다. 이 과정에서 가장 핵심적인 개념 중 하나가 **애그리거트(Aggregate)**입니다. 또한 DDD를 효과적으로 실현하기 위한 아키텍처 스타일로는 **헥사고날 아키텍처(Hexagonal Architecture)**가 널리 활용됩니다. 본 글에서는 애그리거트 설계 시 유의해야 할 팁들과 헥사고날 아키텍처의 적용 방식을 상세히 다루어 보겠습니다.


1. 도메인 주도 설계(DDD) 핵심 개념 정리

1.1 DDD란 무엇인가?

  • 복잡한 소프트웨어를 만들 때 도메인 모델 중심으로 설계하는 방법론
  • 언어의 통일(Ubiquitous Language), 경계(Context), 모델링을 통해 복잡성을 관리
  • 비즈니스 전문가와 개발자 간의 원활한 소통을 목표로 함

1.2 DDD의 주요 요소

  • Entity: 고유한 식별자를 가지는 객체
  • Value Object: 식별자 없이 속성 값으로만 비교되는 객체
  • Aggregate: 여러 Entity와 Value Object를 하나로 묶는 일관성 경계
  • Repository: 애그리거트 단위로 저장소 역할 수행
  • Service: 도메인 로직 중 Entity나 VO에 속하지 않는 연산 담당

2. 애그리거트(Aggregate) 설계 개념

2.1 애그리거트란?

  • 관련 있는 Entity들과 Value Object를 그룹으로 묶은 집합
  • 하나의 루트 엔티티(Aggregate Root)가 존재하며, 외부에서는 루트를 통해서만 접근 가능
  • 내부 일관성(consistency)을 보장해야 하며 트랜잭션 범위의 기준이 됨

2.2 애그리거트의 역할

  • 모델의 경계 정의: 복잡한 모델을 작은 단위로 나눔
  • 트랜잭션 경계 설정: 단일 애그리거트 안에서만 데이터 변경
  • 일관성 관리: 불변 조건을 루트 엔티티가 책임

3. 애그리거트 설계 팁

3.1 트랜잭션 경계를 작게 유지하라

  • 하나의 트랜잭션은 하나의 애그리거트만 수정해야 함
  • 여러 애그리거트를 동시에 변경해야 할 경우 eventual consistency를 고려

3.2 루트 엔티티에서만 외부 접근을 허용하라

  • 루트 외의 엔티티나 값 객체는 루트를 통해서만 접근하고 수정해야 함

3.3 불변 조건(invariant)을 루트에서 검증하라

  • 애그리거트의 상태가 변경될 때마다 불변 조건을 루트가 직접 관리해야 함

3.4 작은 애그리거트가 좋은 애그리거트다

  • 가능하면 애그리거트를 작고 단순하게 유지
  • 필수적으로 함께 변경되는 데이터만 포함

3.5 ID로 참조하라

  • 다른 애그리거트를 참조할 때는 직접 객체 참조 대신 ID(식별자)로만 참조하는 것이 좋음
  • 복잡한 객체 그래프를 피하고 느슨한 결합(loose coupling)을 유지

3.6 불변(Immutable) Value Object를 적극 활용하라

  • VO는 복잡도를 낮추고 부수 효과(side effects)를 줄이는 데 도움이 됨

3.7 변경이 잦은 데이터를 별도 애그리거트로 분리하라

  • 변경이 자주 발생하는 데이터는 별도 애그리거트로 분리하여 수정 충돌을 최소화

4. 애그리거트 설계 예제

예: 주문 시스템(Order System)

  • Order (Aggregate Root)
    • 주문번호(OrderId)
    • 고객정보(CustomerInfo, Value Object)
    • 주문 항목 목록(OrderLineItems, Entity)
  • OrderLineItem (Entity)
    • 상품ID(ProductId)
    • 수량(Quantity)
    • 가격(Price)

→ 외부 시스템은 Order Aggregate Root를 통해서만 주문 항목에 접근하거나 수정 가능


5. 헥사고날 아키텍처(Hexagonal Architecture)

5.1 정의

**헥사고날 아키텍처(Ports and Adapters Architecture)**는 애플리케이션의 비즈니스 로직을 외부 인터페이스(웹, 데이터베이스, 메시징 등)로부터 분리하는 아키텍처 스타일입니다.

5.2 핵심 개념

  • Core (Application/Domain): 비즈니스 로직이 위치
  • Ports (입출력 인터페이스): Core와 외부를 연결하는 인터페이스
  • Adapters (구현체): 포트를 실제로 구현한 외부 컴포넌트

5.3 구조

[External Systems]
    ↓
[Adapters: REST API, DB, Message Queue]
    ↓
[Ports: InputPort, OutputPort]
    ↓
[Application/Domain Layer]

5.4 주요 이점

  • 테스트 용이성 증가
  • 외부 기술에 대한 종속성 최소화
  • 변경에 대한 유연성 증가

6. DDD와 헥사고날 아키텍처의 통합

DDD의 도메인 모델과 헥사고날 아키텍처의 Application Core는 매우 자연스럽게 통합됩니다.

6.1 통합 예시

  • Domain Layer: Entity, Value Object, Aggregate, Domain Service
  • Application Layer: Use Case/Application Service
  • Ports: Repository Interface, External Service Interface
  • Adapters: JPA Repository, REST Controller, Kafka Consumer 등

6.2 주문 시스템 예제 통합 구조

  • Application Service: OrderApplicationService
  • Port: OrderRepository, PaymentGateway
  • Adapter: JpaOrderRepository, ExternalPaymentServiceClient

7. 실전 설계 팁 요약

항목  설계 팁
애그리거트 크기 작고 일관성 있는 단위로 설계
외부 참조 ID 기반 참조로 느슨한 결합 유지
불변 조건 루트 엔티티에서 일관성 강제
트랜잭션 범위 하나의 애그리거트로 제한
헥사고날 적용 도메인 코어는 외부 의존성 제거
테스트 전략 포트 인터페이스 단위 Mocking 가능

8. 결론

**도메인 주도 설계(DDD)**는 복잡한 시스템을 체계적으로 모델링할 수 있는 강력한 방법론이며, 그 중심에는 애그리거트 설계가 있습니다. 트랜잭션 경계를 작게 유지하고, 불변 조건을 루트 엔티티가 책임지게 하며, ID 기반으로 참조하는 방식은 시스템의 복잡성과 부수 효과를 최소화하는 데 크게 기여합니다.

또한, 헥사고날 아키텍처는 이러한 도메인 모델을 외부로부터 깔끔하게 격리할 수 있는 훌륭한 아키텍처 스타일입니다. 도메인 코어를 단단히 지키면서 변화하는 외부 요구사항에도 유연하게 대응할 수 있습니다.

DDD와 헥사고날 아키텍처를 결합하여 견고하고 확장 가능한 시스템을 설계해보시기 바랍니다.