헥사고날 아키텍처

헥사고날 아키텍처의 폴더(패키지) 구조 예제

전통적인 계층형 아키텍처(controller, service, repository, domain 패키지가 나란히 있는 구조)와 달리, 헥사고날 아키텍처는 기능 또는 도메인 중심으로 패키지를 구성합니다.

“온라인 서점”의 “주문(Order)” 기능을 예로 들어보겠습니다.

각 계층별 상세 설명

1.  (가장 핵심, 순수함의 영역)

  • 역할: 비즈니스의 핵심 규칙과 데이터를 담습니다.
  • 규칙: 어떠한 외부 프레임워크나 라이브러리에도 의존해서는 안 됩니다. (jakarta.persistence.*, org.springframework.* 등의 import가 없어야 합니다.)
    • 예시 (Order.java):

2. application (도메인을 지휘하는 응용 로직)

  • 역할: 도메인 객체와 포트를 사용하여 실제 비즈니스 유스케이스(흐름)를 완성합니다.
  • port.in (유스케이스 인터페이스): “무엇을 할 수 있는가”를 정의합니다.
    • 예시 (PlaceOrderUseCase.java):
  • port.out (외부 서비스 의존성 인터페이스): “무엇이 필요한가”를 정의합니다.
    • 예시 (SaveOrderPort.java):
  • service (유스케이스 구현체):
    • 예시 (PlaceOrderService.java):

3. adapter (실제 기술이 구현되는 곳)

  • 역할: 포트를 구현하여 외부 세계와 실제로 상호작용합니다.
  • adapter.in (주도하는 어댑터, Driving Adapter): 외부 요청을 받아 애플리케이션을 ‘주도’합니다.
    • 예시 (PlaceOrderController.java):
  • adapter.out (주도받는 어댑터, Driven Adapter): 애플리케이션의 요청을 받아 외부 시스템과 ‘연동’합니다.
    • 예시 (OrderPersistenceAdapter.java):

왜 이렇게 복잡하게 할까? (장점)

  1. 테스트 용이성 (Testability): PlaceOrderService를 테스트할 때, 실제 DB가 필요 없습니다. SaveOrderPort의 가짜 구현체(Mock Object)를 주입하면 되므로, 빠르고 독립적인 단위 테스트가 가능합니다.
  2. 기술 교체의 유연성 (Flexibility): 만약 데이터베이스를 JPA에서 MyBatis로, 또는 MySQL에서 MongoDB로 바꾸고 싶다면? adapter.out.persistence 패키지만 새로 만들어서 교체하면 됩니다. domain application 코드는 단 한 줄도 건드릴 필요가 없습니다.
  3. 비즈니스 로직 집중: 개발자는 외부 기술에 대한 걱정 없이 domain application 계층에서 순수한 비즈니스 로직 구현에만 집중할 수 있습니다.

초기에는 구조가 복잡해 보일 수 있지만, 애플리케이션의 생명주기가 길어지고 변화에 대응해야 할 때 헥사고날 아키텍처의 진정한 가치가 드러납니다.