본문 바로가기

Architect

Hexagonal Architecture (헥사고날 아키텍쳐) 란?

 

MSA 에 있어서 디커플링된 시스템 아키텍쳐도 중요하지만, 

MSA 역시 작은 어플리케이션의 집합이기 때문에, 어플리케이션 레벨에서의 설계 역시 매우 중요하다.

인프라스트럭쳐 레벨의 큰 관점에서 관심사를 응집시키고, 의존성을 줄였어도

어플리케이션 레벨에서 의존성이 거미줄 처럼 얽혀있고 확장성이 없다면

MSA가 가지는 이점을 결코 활용할 수 없을 것 이다.

 

전통적인 아키텍쳐인 레이어드 아키텍쳐를 먼저 살펴보자.

 

1. 레이어드(Layered) 아키텍쳐

 

레이어드 아키텍쳐를 가지는 어플리케이션은 일반적으로

Presentation Layer, Business Layer, Persistence Layer 세개의 계층을 가진다.

 

레이어드 아키텍쳐는 각 레이어의 응집도를 높히고 레이어 간 결합도를 낮추기 위하여

다음과 같은 규칙을 지킨다.

 

1. 상위 계층이 하위 계층의 인터페이스에 의존한다.

2. 바로 하위 계층만을 호출하며 레이어를 뛰어넘지 않는다.

3. 하위 계층은 자신이 호출되는 상위 계층에 대해 전혀 알지 못하게 설계한다.

 

즉 의존성의 방향이 각 계층의 순서대로 저수준에서 고수준으로 아래로만 흐르는 것이다.

위 규칙으로 인해 DIP 를 만족시킨다.

 

하지만 확장성의 관점에서는 명확히 한계를 갖는다.

인터페이스를 의존하는데 왜 확장성이 한계가 있지? 라는 의문을 가질 수 도 있지만, 더 넓게 생각해보면

하위 계층에 인터페이스에 의존한다는 것은

즉 해당 인터페이스의 추상 특성 이상으로는 확장성을 가지지 못한다는 것이다.

 

이러한 부분이 해결된 헥사고날 아키텍쳐를 살펴보자

 

 

2. 헥사고날(Hexagonal) 아키텍쳐

 

옛날 옛적의 서비스가 아닌 이상, 요즘에는 한 어플리케이션이 외부의 여러 서비스와 의존한다.

데이터 영속화의 대상도 다양한 RDBMS 와 NoSQL 등 적절한 서비스를 선택하고

이미 개발된 여러 3rd party 서비스를 이용하여 불필요한 개발을 줄여 개발속도를 높인다.

MSA 에서는 여러 다른 작은 어플리케이션과 통신해야 한다.

 

전통적인 아키텍쳐에서는 비즈니스로직과 이러한 다양한 비즈니스로직 이외의 것들에 대한

의존성을 없애는 것이 쉽지 않았고 헥사고날 아키텍쳐가 등장하게 되었다.

 

헥사고날 아키텍쳐는 '포트 앤드 어댑터' 아키텍쳐 라고도 한다.

 

 

 

헥사고날 아키텍쳐는 고수준인 비즈니스 로직을 내부 영역으로 응집시키고 

외부와의 통신과 같은 저수준의 것들을 Adapter 로서 외부 영역에 배치 시킨다.

 

내부 영역에는 핵심 비즈니스 로직을 내부로 숨기고

외부 영역의 인바운드를 받아들일 포트와 외부로 처리 결과를 내보낼 아웃바운드 포트를 제공한다.

 

위 그림에서는 Foo 서비스가 인바운드 포트

메시징 인터페이스 리포지토리 인터페이스가 아웃바운드 포트이다.

 

외부 영역에는 외부 서비스나 인프라스트럭쳐 혹은 클라이언트와의 통신 등의 인바운드 아웃바운드 만을 담당한다.

외부 영역에 놓일 어댑터로는 그림과 같이 RestController, 메시지 컨슈머, Persistence DAO 등이 올 수 있다.

 

헥사고날 아키텍쳐가 가지는 가장 큰 장점은,

비즈니스 로직이 비즈니스 로직 이외에 어떤 것과도 의존성을 갖지 않는다는데 있다.

 

DIP 와 각자의 책임을 철저히 지키면서, 아웃바운드 어댑터는 아웃바운드 포트를

인바운드 어댑터는 인바운드 포트를 또한 각 포트는 내부의 비즈니스 로직을 의존하고

비즈니스 로직은 비즈니스 로직만을 책임진다.

 

사실 내가 볼 때는 철저히 규칙을 지키고, 클린 아키텍쳐와 도메인 주도 설계를 적용한 레이어드 아키텍쳐는

헥사고날 아키텍쳐와 크게 다르지 않지만,  인아웃 바운드 포트/ 어댑터를 개념화 한데 의의가 있다고 느껴진다.

 

 

 

 

'Architect' 카테고리의 다른 글

[DDD] 도메인 주도 설계의 요소  (0) 2022.03.03
[DDD] Aggregate 어그리거트  (0) 2022.02.02
[DDD] BoundedContext 바운디드 컨텍스트  (0) 2022.02.02