본문 바로가기
아키텍쳐를 고민하기

헥사고날 아키텍처(Hexagonal Architecture) 코드로 이해 해보기

by simplify-len 2022. 4. 29.

EventsJdbcEntityRecordPublishedEventService 이 부분은 '만들면서 배우는 클린 아키텍쳐' 의 책을 보고 배운점과 느낌점을 설명합니다.

 

헥사고날 아키텍쳐란 무엇인까요?

헥사고날 아키텍쳐는 레이어드 아키텍처(Layered Architecture)의 단점을 해결하기 위해 나왔습니다.

어떻게 해결했는가? 바로 의존성의 역전법칙입니다.

우리가 흔히 아는 레이어드 아키텍쳐는 위에서 아래로 의존성을 가진 형태를 의미합니다.

그림 1 - 전통적인 레이어드 아키텍쳐

 

여기서 만약 의존성 역전 법칙을 활용하면 아래와 같은 아키텍쳐로 변경되어집니다.

그림 2 - 의존성 역전 법칙을 적용한 아키텍쳐

 

이런 형태를 각 계층마다 적용하다 보니, 핵사고날 아키텍쳐의 형태를 띄게 됩니다.

그림 3 - 육각형 아키텍쳐

 

육각형 안에는 도메인 엔티티와 상호작용하는 유즈케이스가 있고, 모든 의존성을 엔티티를 향해 있습니다.

그 외 외부에는 웹 브라우저와 상호작용하는 웹 어탭터도 있고, 일부 어댑터는 외부 시스템과 상호작용하며, 데이터베이스와 상호 작용하는 어댑터가 있습니다.

 

흔히 핵사고날 아키텍쳐를 포트&어탭터 패턴이라 말하는 이유가 바로 위 그림에서 표현하고 있습니다.

 

 애플리케이션 코어와 어탭터 간의 통신이 가능하려면 애플리케이션 코어가 각각의 포트를 제공하고, 주도하는(driving) 어댑터에게는 그러한 포트가 코어에 있는 유즈케이스 클래스에 의해 구현되어 호출되는 인터페이스가 될 것이고, 주도되는(driven)어댑터에게는 그러한 포트가 어댑터에 의해 구현되고 코어에 의해 호출되는 인터페이스가 될 것입니다.

 

큰 그림을 그려봤으니, 이번에는 코드 패키지 구조로 자세히 살펴보려 합니다.

패키지 구조

 크게 Adapter / Application / Domain 으로 나눠지고, Adapter 은 in / out 패키지를 가지며, Application 은 Port 와 Service 를 가집니다.

 

각각의 패키지가 커버하고 있는 부분

 

각각이 가진 책임은 다음과 같습니다.

유즈케이스 

  • 웹으로부터 입력을 받는다.
  • 비즈니스 규칙을 검증한다.
  • 모델 상태를 조작한다.
  • 출력을 반환한다.

유즈케이스 코드

위 그림과 같이 UseCase 는 인터페이스로 존재하며, 구현체 Service는 입력 포트와 출력 포트를 가진다.

LoadEventPort, RecordEventPort 는 웹 어탭터의 출력 포트를 통해 out/persistenceAdapter 와 통신하게 됩니다.

 

 

웹 어탭터

 

웹 브라우저를 통해 상호작용할 수 있는 UI나 다른 시스템에서 우리 애플리케이션으로 호출하는 방식으로 상호작용하는 HTTP API가 여기에 해당됩니다. 

 

그렇다면 웹 어탭터의 책임은 무엇일까요?

  • HTTP 요청을 자바 객체로 매핑하기.
  • 권한을 검사하기
  • 입력 유효성 검증하기
  • 입력을 유스케이스의 입력 모델로 매핑하기
  • 유즈케이스 호출하기
  • 유즈케이스의 출력을 HTTP로 매핑하기
  • HTTP 응답을 반환하기.

 

웹 어댑터가 말하는 책임에 대해서는 코드로서 표현되어집니다.

 

 

 

영속성 어탭터

 

영속성 어탭터는 데이터베이스를 쿼리하거나 변경하는 데 사용할 수 있는 포맷으로 입력 모델을 매핑합니다. 

위 RecordPublishedEventService 의존성 주입되었던  LoadEventPort, RecordEventPort 의 구현체가 바로 여기 영속성 어탭터에 있습니다.

 

그렇다면 영속성 어탭터가 가진 책임은 어떤게 있을까요?

  • 입력을 받는다.
  • 입력을 데이터베이스 포맷으로 매핑한다.
  • 입력을 데이터베이스로 보낸다.
  • 데이터베이스 출력을 애플리케이션 포맷으로 매핑한다.
  • 출력을 반환한다.

 

 

아직 도메인에 대한 이야기를 하지 않았습니다.

도메인 굉장히 심플하고 또한 이야기 할만한 부분이 크게없었습니다. 왜냐하면 POJO 형태를 띄고 있기 때문입니다.

 

인상깊었던 부분과 나의 생각

1. 엔티티와 도메인을 분리되어진다
도메인은 POJO 형태를 띄어 이야기할만한 부분이 없다라고 언급했지만, 인상깊었던 부분 또한 도메인 영역이였습니다. 우리는 ORM 을 활용해 많은 개발이 이루어집니다.  그러다보니, 도메인영역과 인프라영역이 혼재되는 코드가 생기게 됩니다. 이 부분을 명확하게 영속성이 관리하는 Entity 와 도메인이라 불리는 Pojo 로 나누게 되는데, 이렇게 됨으로써 명확해짐을 알 수 있었습니다.

  • EventsJdbcEntity
  • Events

 

2. 의존성 역전 법칙은 많은 코드를 만들어 낸다.

 

 

댓글