Architecture

도메인 중심 설계의 정석: Hexagonal Architecture + DDD + CQRS 아키텍처 통합 정리

구루싸 2025. 4. 9. 19:02
반응형
SMALL

현대의 백엔드 시스템은 복잡한 도메인 로직, 다양한 외부 인터페이스, 그리고 높은 변경 요구사항을 수용해야 합니다. 이런 복잡성을 견고하게 다루기 위해 자주 언급되는 세 가지 개념이 있습니다:

  • Hexagonal Architecture (육각형 아키텍처)
  • DDD (Domain-Driven Design)
  • CQRS (Command Query Responsibility Segregation)

이 글에서는 이 세 가지를 어떻게 함께 결합하여 클린하고 유연한 아키텍처를 구성할 수 있는지 정리해보겠습니다.


1. Hexagonal Architecture (포트 & 어댑터 아키텍처)

핵심 아이디어

  • "도메인 로직은 외부 세계와 분리되어야 한다."
  • 핵심 도메인 로직을 중심(안쪽)에 두고, 외부와의 상호작용을 "포트(Ports)"와 "어댑터(Adapters)"를 통해 주입합니다.

구성 요소

  • Application Core (도메인 + 유스케이스)
  • Ports: 도메인 레이어가 외부에 기대하는 인터페이스 (예: UserRepository, NotificationPort)
  • Adapters: 실제 외부 구현 (예: DB, REST API, 메시지 큐)

장점

  • 외부 의존성으로부터 도메인을 보호
  • 테스트 용이 (Mock Port로 대체 가능)
  • 구현 세부사항을 쉽게 교체

2. DDD (Domain-Driven Design)

핵심 아이디어

  • "비즈니스 복잡성을 도메인 모델로 표현하자."
  • 도메인을 중심으로 모델링하고, 코드 구조도 도메인 개념에 맞춰 정리

주요 개념

  • Entity: 고유 ID로 식별되는 객체 (예: Order, User)
  • Value Object: 값 자체로 의미가 있는 불변 객체 (예: Money, Email)
  • Aggregate: 일관성 경계를 가지는 도메인 객체 묶음
  • Repository: Aggregate를 저장하고 조회하는 인터페이스
  • Domain Service: 하나의 Entity에 속하지 않는 도메인 로직
  • Application Service: 유스케이스 단위의 로직을 담당

3. CQRS (Command Query Responsibility Segregation)

핵심 아이디어

  • "명령(Command)과 조회(Query)를 분리하자."
  • 상태 변경과 조회를 서로 다른 모델로 관리

구조

  • Command Model: 데이터를 변경하는 모델 (쓰기 전용)
  • Query Model: 데이터를 읽는 모델 (읽기 전용)
  • 서로 다른 DB를 사용할 수도 있음 (eventual consistency)

장점

  • 성능 최적화 (읽기/쓰기 분리)
  • 복잡한 도메인 로직 처리 시 유연성 증가
  • Event Sourcing과 결합 시 강력함

4. 세 가지의 통합 설계

아키텍처 다이어그램 (간단한 구조)

                        [ REST / GraphQL / CLI ]
                                   │
                            ┌──────┴───────┐
                            │ Application │   ← 유스케이스 (CQRS 기준 Command/Query 구분)
                            └──────┬───────┘
                                   │
                            [ 도메인 모델 (DDD) ]
                                   │
                            ┌──────┴──────┐
                            │   Ports    │   ← 추상화된 인터페이스
                            └──────┬──────┘
                    ┌─────────────┴────────────┐
                [ DB Adapter ]         [ External Service Adapter ]
              (JPA, SQL, NoSQL 등)    (Email, Payment, etc.)

5. 예시 흐름: 주문 생성

  1. 사용자가 주문 생성 요청을 보냄 (Command)
  2. OrderApplicationService가 도메인 로직 수행
  3. OrderAggregate에서 유효성 검사 및 비즈니스 규칙 실행
  4. OrderRepository 포트를 통해 DB에 저장
  5. 외부 어댑터(예: 메시지 큐)를 통해 알림 전송

6. 결론

이 세 가지 아키텍처를 조합하면 다음과 같은 효과를 기대할 수 있습니다:

  • 도메인 중심의 명확한 구조
  • 외부 의존성 최소화
  • 변경에 강하고 테스트 가능한 아키텍처
  • 성능과 확장성 고려된 설계

각각의 개념은 따로 보아도 강력하지만, 서로를 보완하며 함께 쓸 때 진가를 발휘합니다.


참고 자료

  • 《도메인 주도 설계 시작하기》 - Vladik Khononov
  • 《Implementing Domain-Driven Design》 - Vaughn Vernon
  • Hexagonal Architecture 원 논문 - Alistair Cockburn
  • Microsoft DDD + CQRS Guide





반응형
LIST