CS

DDD, 헥사고날 아키텍처, 멀티모듈 — 개념 및 흐름

KJihun 2025. 9. 14. 14:40
728x90

들어가며

현대 애플리케이션은 복잡한 비즈니스 규칙과 빠른 기술 교체 요구를 동시에 맞닥뜨린다.

이를 잘못 설계하면 코드가 외부 라이브러리·프레임워크에 묶여 변경이 어렵고, 여러 팀이 동시에 작업할 때 충돌이 잦아진다.

DDD, 헥사고날, 멀티모듈은 이러한 문제를 해결하는 실용적인 조합이다.

 

이 글은  DDD → 헥사고날 → 멀티모듈 순으로 설명할 예정이다.

 

 


 

도메인 주도 설계 (DDD; Domain-Driven Design)

도메인 주도 설계.. 알듯 말듯한 단어이다. 

도메인 중심으로 설계를 한다는 것 같은데.. 

과연 DDD에서 말하는 도메인은 무엇일까? 🤔

DDD에서 도메인은 현실 세계에서 해결해야 하는 비즈니스 문제 영역을 정의하는 것이라 볼 수 있다.

예를들어 티켓 예매 프로그램을 만든다고 가정할 경우

  • 예매(티켓 발급, 결제, 취소, 환불 등)
  • 사용자(회원가입, 로그인, 프로필 관리 등)
  • 공연(공연 일정, 좌석 배치, 공연 정보 등) 

그렇다면 객체와 어떤 차이점이 있을까?

도메인이 현실 세계에서 해결해야 하는 비즈니스 문제 영역을 정의한다면

객체는 그 문제 영역을 소프트웨어 안에서 구현하는 구체적인 단위다. (예: Order 엔티티, PaymentService)

다음으로는 DDD 의 계층에 대해 간단하게 알아보자.

 

 

DDD의 계층 구조

 

총 4개의 계층을 가진다.

  1. Presentation Layer (UI Layer)
    • 사용자의 요청을 받아 Application Layer 에 전달하는 계층
    • Client로부터 request를 받고 response를 return 하는 API
    • 웹 애플리케이션 기준 Controller가 대표적인 구현체
  2. Application Layer
    • Domain Layer에 구현된 메서드호출하여 하나의 기능을 수행하는 계층
    • 여러 도메인 메서드를 호출하고 순서를 제어
    • 여러 도메인 호출을 하나의 트랜잭션으로 묶음
    • 논리적 검증이나 데이터 기반 접근 제어
  3. Domain Layer
    • 기능별로 비즈니스 로직을 작성하는 계층
    • 기능별로 메서드로 작성하여야 하며, Application Layer가 호출하여 사용한다
  4. Infrastructure Layer
    • DB 접근(JPA, JDBC), 메시지 브로커, 외부 API 연동 등 외부와의 통신을 담당하는 계층
    • 해당 계층에서 얻어온 정보를 다른 계층에 전달하는 역할

 


 

헥사고날 아키텍처 (Hexagonal Architecture / Ports & Adapters)

DDD에서 말하는 도메인은 외부 기술(JPA, DB, 프레임워크 등)에 의존하지 않고 순수한 비즈니스 규칙을 표현해야 한다.
하지만 일반적인 계층형 아키텍처에서는 도메인 코드가 외부 기술과 강하게 결합되어, DB를 바꾸거나 프레임워크를 교체할 때 도메인까지 수정해야 하는 문제가 발생한다.

이를 해결하기 위한 패턴이 헥사고날 아키텍처(Hexagonal Architecture)이다.

 

헥사고날 아키텍처의 핵심

도메인은 외부를 직접 알지 못하고, 포트(Port, 추상화 인터페이스)만을 알고 있으며,

실제 동작은 어댑터(Adapter, 구현체)가 담당한다는 것이다.

 

Hexagonal Architecture의 계층 구조

  1. Domain Core (중앙)
    • POJO 도메인 코드(인프라 의존성 없음)
    • 예: Entity, VO, Service
  2. Ports (인터페이스)
    • 도메인이 외부에 기대는 기능 추상화
    • 예: OrderRepository, PaymentGateway
  3. Adapters (구현체)
    • 포트를 실제 기술로 구현
    • 예: JpaOrderRepository, StripePaymentGatewayAdapter
    • Inbound Adapter: 외부 요청 들어오는 곳 (REST Controller, CLI, MQ Consumer)
    • Outbound Adapter: 외부로 나가는 곳 (DB, Kafka, API)

 

 

 


 

멀티모듈 (Multi-module)

헥사고날 아키텍처를 통해 도메인과 기술 구현체를 명확히 분리하면,
도메인은 외부 변화에 영향을 받지 않고 안정적으로 유지할 수 있다.

하지만 프로젝트 규모가 커지고 여러 도메인이 함께 존재하면,
코드가 한 프로젝트 안에 섞여 관리되면서 복잡성이 커지고 유지보수성이 떨어질 수 있다.
이를 해결하는 방법 중 하나가 멀티모듈 구조(Multi-Module Architecture)이다.

 

 

멀티모듈은 하나의 프로젝트를 역할이나 도메인 단위로 나누어 관리하는 방식이다.
즉, 애플리케이션 전체를 하나의 거대한 모놀리식 코드베이스로 두지 않고,
도메인별 / 계층별 / 공통 모듈별로 나누어 각각 독립적인 모듈로 관리한다.

 

 

멀티모듈의 계층 구조 예시

멀티모듈은 헥사고날 아키텍처와 결합하여 사용할 때 가장 큰 효과를 발휘한다.
예를 들어, 공연 예매 시스템을 멀티모듈로 나눈다면 다음과 같은 구조를 가질 수 있다

project-root/
 ├─ ticket-domain/         🎟️ 티켓 도메인 (Entity, VO, Domain Service)
 ├─ ticket-application/    🎟️ 티켓 애플리케이션 서비스 (유스케이스, 트랜잭션 관리)
 ├─ ticket-infra/          🎟️ 티켓 인프라 (DB, 외부 API, Messaging)
 │
 ├─ user-domain/           👤 사용자 도메인
 ├─ user-application/      👤 사용자 애플리케이션 서비스
 ├─ user-infra/            👤 사용자 인프라
 │
 ├─ common/                🛠️ 공통 유틸리티, 공용 DTO, 에러 처리
 └─ app/                   🚀 실제 실행 진입점 (API 서버, Batch, CLI)
  • Domain: 순수한 비즈니스 로직 (POJO), 외부 의존성 없음
  • Application: 유스케이스, 트랜잭션 제어, 도메인 서비스 orchestration
  • Infra: Port의 구현체, DB/JPA, 메시징, 외부 API 연동
  • App: Controller, Batch Job, MQ Consumer 등), 최종 실행 가능 애플리케이션

 

이 계층 구조를 헥사고날 아키텍처와 결합하면

  • Domain = Core
  • Application = Service Orchestration
  • Infra = Outbound Adapter
  • App = Inbound Adapter

로 자연스럽게 매핑된다.

 

 

멀티모듈 분리 시 얻을 수 있는 이점

  1. 관심사 분리: 도메인·공통·외부 연동 등을 모듈 단위로 나누어 코드 가독성과 유지보수성을 높임
  2. 재사용성 증대: 공통 모듈을 여러 서비스에서 활용할 수 있어 중복을 줄이고 일관성을 확보
  3. 의존성 관리 용이: 모듈별로 필요한 라이브러리만 의존하도록 설정해 빌드 크기와 충돌 위험을 줄임
  4. 병렬 개발 및 협업 효율성: 팀 단위로 모듈을 분리해 독립적으로 개발·테스트 가능 → 충돌 최소화
  5. 확장성과 안정성: 새로운 기능 추가 시 기존 모듈에 영향을 덜 주며, 특정 모듈만 교체하거나 개선 가능

 

멀티모듈 구조는 모듈 단위로 코드를 나누어 각 모듈이 필요한 의존성만 가지도록 설계함으로써, 빌드 속도를 줄이고 불필요한 라이브러리 충돌을 최소화할 수 있다.
이렇게 명확하게 모듈 경계를 설정하면, 여러 개발자가 동시에 같은 코드베이스에서 작업하더라도 충돌 가능성을 줄이고 독립적인 개발이 가능해진다.

또한, 각 모듈이 독립적인 단위로 관리되기 때문에, 서비스 확장이 필요할 때는 특정 모듈만 교체하거나 개선하는 것이 용이하며, 전체 애플리케이션에 미치는 영향을 최소화할 수 있다.

즉, 멀티모듈은 빌드 효율과 의존성 관리의 기술적 장점을 제공함과 동시에, 팀 단위 협업과 서비스 확장성까지 자연스럽게 지원하는 구조라고 볼 수 있다.

 

 

결론

DDD를 통해 문제 영역을 명확히 정의하고,
헥사고날 아키텍처로 도메인을 외부 기술로부터 철저히 격리하며,
멀티모듈 구조로 코드베이스를 역할 단위로 나누면,

결과적으로 변화에 유연하고 유지보수가 쉬우며, 팀 단위 협업과 확장성까지 고려한 견고한 아키텍처를 구현할 수 있다.