Files
2nd/10_Wiki/Topics/Hexagonal Architecture.md
T
2026-05-02 23:33:34 +09:00

10 KiB

id, category, confidence_score, tags, last_reinforced
id category confidence_score tags last_reinforced
P-REINFORCE-WIKI-B437D29F Unified 0.95
hexagonal-architecture
clean-architecture
의존성-역전-(dependency-inversion)
layered-architecture-pattern
microservices-architecture-pattern
architecture-principles
2026-05-02

Hexagonal Architecture

📌 Brief Summary

헥사고날 아키텍처(Hexagonal Architecture) 또는 포트와 어댑터(Ports and Adapters) 패턴은 비즈니스 로직을 데이터베이스, UI, 프레임워크 등 외부 시스템으로부터 분리하여 느슨하게 결합된 애플리케이션을 만드는 설계 패턴이다 [1, 2]. 알리스테어 코오번(Alistair Cockburn)이 창안한 이 구조는 의존성의 방향이 철저히 시스템 중심부를 향하도록 설계되어, 외부 기술의 변화가 핵심 비즈니스 규칙에 영향을 미치지 않게 보호한다 [2, 3]. 결과적으로 시스템의 높은 테스트 용이성(Testability), 유지보수성, 그리고 유연한 기술 스택 교체를 가능하게 한다 [4, 5].

📖 Core Content

  • 핵심 도메인(Domain/Core): 시스템의 중심에 위치하며, 외부 시스템(UI, 데이터베이스 등)에 대한 어떠한 의존성도 갖지 않는 순수한 비즈니스 로직과 규칙을 포함한다 [1, 3, 6].
  • 포트(Ports): 코어 영역이 외부 세계와 소통하는 방식을 정의하는 추상화된 인터페이스 계층이다 [3, 6].
    • 인바운드(Driving/Input) 포트: 사용자의 입력이나 외부 API 호출이 코어 로직과 상호작용하는 진입점을 정의한다 [1, 6].
    • 아웃바운드(Driven/Output) 포트: 코어가 데이터 영속성이나 외부 메시징 시스템 등 외부 인프라와 상호작용하는 방식을 정의한다 [1, 6].
  • 어댑터(Adapters): 외부 시스템과 도메인의 포트를 연결하는 구체적인 구현체로, 외부에서 들어오거나 나가는 데이터를 변환하는 역할을 한다 [3, 6].
    • 기본(Primary) 어댑터: HTTP 요청이나 사용자 입력을 코어가 이해할 수 있는 명령으로 번역한다 [1].
    • 보조(Secondary) 어댑터: 아웃바운드 포트를 구현하여 실제 외부 데이터베이스 쿼리나 서비스 호출을 수행한다 [1, 6].
  • 의존성 역전(Dependency Inversion)과 구조적 분리: 전통적인 계층형 아키텍처(Layered Architecture)가 프레젠테이션 ➔ 비즈니스 ➔ 데이터베이스 방향의 하향식 의존성을 가지는 반면, 헥사고날 아키텍처는 비즈니스를 중앙에 두고 프레젠테이션과 데이터베이스 모두가 비즈니스 계층을 향해 의존하도록(프레젠테이션 ➔ 비즈니스 ⬅ 데이터베이스) 의존성을 역전시킨다 [3, 7].
  • 보안 및 경계 통제: 포트와 어댑터를 엄격히 정의함으로써 UI 계층에서 직접 데이터베이스에 접근하는 등의 불안전한 관행을 방지한다 [8]. 입력 유효성 검사, 접근 제어 등 보안 메커니즘을 어댑터 경계에서 강제할 수 있어 핵심 도메인 로직이 손상되는 것을 보호한다 [8, 9].

⚖️ Trade-offs & Caveats

  • 높은 초기 복잡성과 가파른 학습 곡선: 포트와 어댑터를 설계하고 구현하는 방식은 초기에 복잡하며, 경험이 적은 개발자 팀에게는 가파른 학습 곡선을 요구한다 [4, 10].
  • 보일러플레이트 코드와 성능 오버헤드: 동일한 목적을 위해 포트 인터페이스와 어댑터 구현체를 분리하여 작성해야 하므로 보일러플레이트 코드(반복 코드)가 증가한다 [4]. 또한, 추가된 추상화 계층들로 인해 약간의 성능 오버헤드(Performance Overhead)가 발생할 수 있다 [4, 11].
  • 단순 프로젝트 적용 시의 비효율성 (Over-engineering): 최소한의 비즈니스 로직만을 가진 단순한 CRUD(Create, Read, Update, Delete) 애플리케이션이나 마감 기한이 매우 촉박한 프로젝트에 도입할 경우, 아키텍처가 주는 이점보다 설정 및 설계 비용이 더 커지는 오버엔지니어링 문제가 발생한다 [12, 13].
  • 반대 급부(Trade-off)로서의 유지보수성: 초기 구축 비용과 복잡성, 약간의 성능 저하를 감수하는 대신, 데이터베이스나 프레임워크 같은 외부 기술이 변경될 때 핵심 로직을 수정할 필요가 없으며 독립적인 격리 테스트(Unit Testing)가 매우 쉬워진다는 강력한 유지보수적 이점을 얻는다 [4, 5, 14].

🔗 Knowledge Connections

[아키텍처/기반 설계 철학]

  • Clean Architecture
    • 연결 이유: 헥사고날 아키텍처와 마찬가지로 도메인(Entities/Use Cases)을 중앙에 배치하고 의존성을 안쪽으로 향하게 하여 외부 요인으로부터 비즈니스 로직을 격리하는 공통의 철학을 발전시킨 패턴이다 [14, 15].
    • 이 개념을 통해 더 깊게 이해할 수 있는 부분: 아키텍처가 동심원 계층으로 더욱 세분화될 때 헥사고날의 '포트와 어댑터' 개념이 어떻게 '인터페이스 어댑터'로 구조화되는지 이해할 수 있다 [16].
  • 의존성 역전 (Dependency Inversion)
    • 연결 이유: 외부 데이터베이스 기술이 비즈니스 계층에 의존하도록 만드는 헥사고날 및 도메인 중심 설계 아키텍처의 가장 근본적인 원리다 [3, 17].
    • 이 개념을 통해 더 깊게 이해할 수 있는 부분: 제어 흐름과 소스 코드 의존성의 방향을 분리하는 객체 지향 설계 원칙을 이해할 수 있다.

[비교/대조 아키텍처 구조]

  • Layered Architecture Pattern
    • 연결 이유: 헥사고날 아키텍처와 달리 기술적 관점의 수평적 층(UI, 비즈니스, 데이터)으로 나뉘며 의존성이 하향식으로 흐르는 고전적 아키텍처다 [7, 18, 19].
    • 이 개념을 통해 더 깊게 이해할 수 있는 부분: 왜 현대 시스템이 단순한 Layered 구조에서 벗어나 포트와 어댑터 구조로 진화해야만 했는지(도메인 보호의 필요성) 그 한계를 대조해 볼 수 있다 [13, 20].
  • Microservices Architecture Pattern
    • 연결 이유: 헥사고날 아키텍처는 마이크로서비스 생태계 내에서 각 개별 서비스 단위의 내부 아키텍처를 견고하게 설계하는 데 훌륭하게 결합(시너지)된다 [5, 21].
    • 이 개념을 통해 더 깊게 이해할 수 있는 부분: 거시적 시스템(Microservices) 내에서 미시적 컴포넌트(Hexagonal)가 어떻게 설계되어 기술 스택 독립성을 확보하는지 파악할 수 있다.

Deeper Research Questions

  • 헥사고날 아키텍처의 인바운드(Driving) 포트와 아웃바운드(Driven) 포트 간의 설계적 차이점은 무엇이며, 코드 레벨에서 이를 구현할 때 제어 흐름(Control Flow)은 어떻게 달라지는가?
  • 단순한 CRUD 위주의 스타트업 MVP 프로젝트에 헥사고날 아키텍처를 도입했을 때 발생하는 오버엔지니어링(Over-engineering)의 구체적인 비용과 대안은 무엇인가?
  • 레거시 계층형 아키텍처(Layered Architecture)를 헥사고날 아키텍처로 점진적 리팩토링(Incremental Refactoring)하기 위한 가장 안정적인 전략은 무엇인가?
  • 어댑터(Adapter) 계층에서 외부 API나 데이터베이스의 데이터 구조를 내부 도메인 모델로 변환할 때, 성능 오버헤드를 최소화하고 데이터 정합성을 유지하는 최적의 매핑(Mapping) 방법은 무엇인가?
  • 마이크로서비스 아키텍처(MSA) 환경에서 헥사고날 아키텍처를 각 서비스 내부에 적용하는 것이, 외부 서비스 통신 변경이나 분산 환경 기술 스택 교체에 어떻게 회복 탄력성을 부여하는가?

Practical Application Contexts

  • Implementation: 핵심 비즈니스 로직 코드를 작성할 때, 데이터베이스 접근이나 외부 HTTP 통신 코드를 직접 작성하는 대신 순수 인터페이스(Port)만 정의한다. 이후 외부 프레임워크(Spring, Express 등)에 의존하는 구체적인 Adapter 클래스를 만들어 인터페이스를 구현한다 [1, 3, 6].
  • System Design: 진화하는 비즈니스 규칙이 포함된 전자상거래나 뱅킹 시스템, 또는 데이터베이스/프레임워크 교체가 빈번히 일어날 수 있는 장기 유지보수 지향 애플리케이션의 골격으로 활용된다 [12, 22, 23].
  • Operation / Maintenance: 외부 서비스 공급자(예: 결제 게이트웨이 Stripe에서 PayPal로 변경)나 데이터베이스(예: Oracle에서 PostgreSQL로 변경)를 교체해야 할 때 시스템의 코어 로직은 전혀 건드리지 않고 외부의 Adapter 계층만 교체하므로 운영 중단 위험과 유지보수 부담이 획기적으로 줄어든다 [5, 22].
  • Learning Path: 기본적인 소프트웨어 디자인 패턴을 학습한 뒤, 전통적인 계층형 아키텍처(Layered)의 강한 결합 문제점을 인지하고, 이를 해결하기 위한 '의존성 역전 원칙(DIP)'과 '관심사 분리'를 배우면서 헥사고날 아키텍처 및 클린 아키텍처로 지식을 확장해 나간다 [24, 25].
  • My Project Relevance: 소스에 관련 정보가 부족합니다. (사용자의 개별 프로젝트에 대한 구체적 문맥은 소스 데이터에 포함되어 있지 않습니다.)

Adjacent Topics

  • Modular Monolith
    • 확장 방향: 마이크로서비스의 운영 복잡성을 피하기 위해 단일 배포 단위를 유지하면서도, 내부적으로 헥사고날 아키텍처와 같은 엄격한 도메인 경계를 가져가는 하이브리드 진화 형태를 학습할 수 있다 [26, 27].
  • Domain-Driven Design (DDD)
    • 확장 방향: 헥사고날 아키텍처의 중앙에 위치하는 '핵심 비즈니스 로직'을 도메인 객체와 애그리거트(Aggregate) 단위로 어떻게 효과적으로 모델링하고 분리할 수 있는지 설계론적 측면으로 확장한다 [5, 28].

Last updated: 2026-05-02