헥사고날 아키텍처

계층형 아키텍처의 문제점

웹 애플리케이션을 개발해 본 경험(특히 스프링)이 있다면 가장 익숙한 아키텍처는 계층형 아키텍처(Layered Architecture) 일 것이다. 이 아키텍처는 정해진 계층수에 따라 N개의 N-계층(N-tier) 아키텍처라고도 하며 이해하기 쉽고 제약사항이 별로 없어서 표준과 같이 사용되기도 했다.

layered-architecture

계층형 아키텍처는 상위계층이 하위계층에 대한 의존성을 가진다. 이러한 의존성은 다음과 같은 문제가 존재한다.

  • 데이터베이스 주도 설계
    • 인프라 계층의 주요 요소인 데이터베이스
    • 의존성 방향으로 인해 데이터베이스를 가장 먼저 설계하고 개발
      • 특히 JPA와 같은 ORM을 사용하면서 테이블에 해당하는 엔티티를 먼저 만들도록 함 (계층형 아키텍처에서는 이게 합리적인 방법임).
    • 도메인의 행위가 아니라 저장할 구조를 먼저 설계하도록함
      • 도메인계층과 영속성(인프라)계층의 구분(역할)을 없애기도 함
  • 인프라 도구 변경의 어려움
    • 경우에 따라 모든 계층의 수정이 필요할 수도 있음
      • JPA에서 MyBatis로 변경이 필요한경우
      • MSA 구성시 서비스간 통신 방법 변경이 필요한경우
  • 테스트하기 어렵게 만듦
    • 상위 계층을 테스트할때는 하위 계층을 알아야함
    • 즉 도메인계층을 분리해서 테스트할 수 없고 영속성 계층을 알아야 가능함

이처럼 계층간 의존성으로 인해 발생하는 문제점을 최대한 해결한 헥사고날 아키텍처이다.

선택할 수 있는 모든것들에 대해서는 트레이드 오프가 존재합니다. 조직 문화 또는 규모, 개발자의 숙련도, 제품의 목적에 따라 계층형 아키텍처는 좋은 선택이 될 수 있습니다.

도메인을 외부로부터 분리한 헥사고날 아키텍처

헥사고날 아키텍처는 의존성 역전 원칙을 사용해서 도메인을 외부(인프라 등)에 대한 의존성으로 부터 분리한 아키텍처이다. 의존성 역전을 위한 포트&어댑터 패턴을 사용하기 때문에 포트&어댑터(Port & Adpater)아키텍처라고도 한다.

의존성 역전 원칙과 포트&어댑터

의존성 역전 원칙은 클린 아키텍처에서 소개된 개념으로 추상체(자바의 인터페이스)와 이를 구현(자바의 implement)하는 구현체로 분리해 의존성 방향을 역전하는 방법이다. 즉 도메인은 인프라를 의존하지 않고 도메인 내부(자바에서는 패키지)에 있는 추상체를 사용한다.

hexagonal-architecture

추상체를 포트, 구현체를 어댑터로 표현하기 때문에 포트&어댑터 아키텍처라고도 한다. 추가적으로 포트를 in과 out이라는 개념으로 포트를 구분하는데 in은 호출하는(인터페이스와 같은 도메인을 호출하는 영역), out은 호출되는(데이터베이스와 같은 도메인에 의해 호출되는)를 의미한다.

hexagonal

PoC

헥사고날 아키텍처의 핵심은 도메인이 외부에 대한 의존성을 가지지 않는것이다. 이를 위해 의존성 역전 원칙을 사용했는데 그렇다면 의존성을 가지지 않는다는 것은 어떻게 확인할까? 실제 구현해서는 패키지로 도메인을 구분해서 확인할 수 있다.

module
  ├─ adapter
  │    ├─ in
  │    └─ out
  ├─ domain
  └─ application
       ├─ port
       │    ├─ in
       │    └─ out
       └── service

위의 패키지 구조를 설명하면 다음과 같다.

  • adapter
    • 외부에서 호출되거나(API 등) 외부를 호출(데이터베이스 등)하는 영역
    • port를 사용해서 application 패키지를 호출
  • domain
    • 도메인 객체
    • 외부의 어떠한 패키지도 의존하지 않음
  • application
    • 도메인 객체를 사용해서 비즈니스 로직을 표현하는 객체
    • domain 패키지를 의존함

모든 코드는 여기서 확인할 수 있습니다.

참고자료