Files
2nd/10_Wiki/Topics/Hexagonal_Architecture.md
T

5.4 KiB

category, tags, title, description, last_updated
category tags title description last_updated
Dev
Architecture
Design Patterns
DDD
SOLID
Hexagonal Architecture (Ports and Adapters) 도메인 로직을 외부 인프라스트럭처로부터 격리하여 시스템의 유연성과 테스트 용이성을 극대화하는 아키텍처 설계 패턴 2026-05-02

Hexagonal Architecture

📌 Brief Summary

헥사고날 아키텍처(Hexagonal Architecture), 또는 포트와 어댑터(Ports and Adapters) 패턴은 소프트웨어의 핵심인 비즈니스 로직(도메인)을 데이터베이스, UI, 프레임워크와 같은 외부 요소로부터 완전히 격리하는 설계 방식입니다. 시스템을 내부(Inside/Domain)와 외부(Outside/Infrastructure)로 명확히 분리하며, 모든 상호작용은 정의된 인터페이스인 **포트(Port)**와 이를 구현하는 **어댑터(Adapter)**를 통해서만 이루어집니다. 이를 통해 기술 스택의 변경이 비즈니스 로직에 미치는 영향을 최소화하고, 독립적인 테스트가 가능한 견고한 시스템을 구축합니다.


📖 Core Content

1. 핵심 원리: 의존성 역전 (DIP)

전통적인 계층형 아키텍처(Layered Architecture)는 상위 계층이 하위 계층(특히 DB나 외부 라이브러리)에 직접 의존하여 기술적 변경에 취약했습니다. 헥사고날 아키텍처는 **의존성 역전 원칙(Dependency Inversion Principle)**을 극한으로 활용하여, 도메인과 인프라 모두가 추상화된 인터페이스(포트)에 의존하게 만듭니다.

2. 주요 구성 요소

  • 도메인 (Inside): 애플리케이션의 핵심 비즈니스 로직과 규칙을 포함하는 순수 코드 영역입니다. 외부 프레임워크나 데이터베이스 기술에 대한 지식이 전혀 없는 상태로 유지됩니다.
  • 포트 (Ports): 내부와 외부를 연결하는 명세(Interface)입니다.
    • 입력 포트 (Inbound/Driving Ports): 외부(UI, API 호출 등)에서 도메인 기능을 호출할 때 사용하는 인터페이스입니다.
    • 출력 포트 (Outbound/Driven Ports): 도메인이 외부 자원(DB, 메시지 큐, 외부 API)에 접근해야 할 때 사용하는 인터페이스입니다.
  • 어댑터 (Outside): 포트를 구체적으로 구현하거나 호출하는 인프라 계층입니다.
    • 입력 어댑터: REST Controller, CLI, WebSockets 등 외부 요청을 도메인이 이해할 수 있는 형식으로 변환하여 입력 포트를 호출합니다.
    • 출력 어댑터: 도메인의 요청을 받아 실제 DB(JPA, MongoDB), 외부 메일 서버, 알림 서비스 등으로 전달하는 구체적인 기술 구현체입니다.

3. 실전 설계 전략 (Framework Specific)

  • Spring Boot (Java): 도메인 모델을 @Entity 등 프레임워크 어노테이션에서 분리하여 POJO로 구성합니다. @Configuration을 사용하여 어댑터 구현체를 런타임에 도메인 서비스에 주입합니다.
  • NestJS (TypeScript): 모듈 시스템과 DI를 활용합니다. Domain, Application, Infrastructure, Presentation 계층을 폴더 구조로 명확히 나누고, 인터페이스 기반 프로그래밍을 강제합니다.

⚖️ Trade-offs & Caveats

Benefits

  • 높은 테스트 용이성: 외부 DB나 API 없이도 모킹(Mocking)을 통해 도메인 로직만 완벽하게 테스트할 수 있습니다.
  • 기술 독립성: 데이터베이스나 메시징 시스템을 교체할 때 도메인 코드를 수정할 필요가 없습니다.
  • 유지보수성: 비즈니스 규칙이 한곳에 집중되어 있어 코드 파악과 변경이 용이합니다.

⚠️ Challenges

  • 초기 복잡성: 단순한 CRUD 앱의 경우, 수많은 인터페이스와 매핑 객체(DTO/Mapper)가 오버헤드로 작용할 수 있습니다.
  • 보일러플레이트: 계층 간 데이터 변환을 위한 코드가 늘어납니다.
  • 학습 곡선: 전통적인 계층 구조에 익숙한 팀에게는 패러다임 전환을 위한 비용이 발생합니다.

🔗 Knowledge Connections

Practical Application Contexts

  • System Design: UI나 DB를 먼저 설계하지 않고, 비즈니스 유스케이스와 포트를 먼저 정의하는 '도메인 중심' 접근을 권장합니다.
  • Maintenance: 레거시 시스템을 점진적으로 개선할 때, 외부 통신부를 어댑터로 격리하여 안전하게 로직을 추출할 수 있습니다.

💡 Adjacent Topics

  • Test_Driven_Development: 헥사고날의 격리성을 활용하여 테스트 중심 개발을 가속화합니다.
  • CQRS: 대규모 시스템에서 명령(Write)과 조회(Read) 포트를 분리하여 성능을 극대화하는 전략과 궁합이 좋습니다.
  • Microservices: 각 마이크로서비스 내부 아키텍처로 헥사고날을 적용하여 서비스 간 독립성을 확보합니다.

Last updated: 2026-05-02