Layered Architecture 의 단점 때문에 대두되고 있는게 Hexagonal Architecture 입니다.
예시를 들어보겠습니다.
Order 란 엔티티를 만들었습니다. 그리고 Order 를 도메인 객체로 사용하고 있습니다.
자연스럽게 JPA 란 기술을 사용하면서 Order 란 객체와 Orders 란 테이블 간의 맵핑을 해주기 위해 Order 에 @Entity, @OneToMany 등을 선언하면서 DB 맵핑과 관련된 JPA 에서 사용하는 어노테이션들을 달았죠.
그런데 좀 더 생각해보면 “Order 는 데이터베이스와 맵핑하기 위해서 나온 객체고, Order 객체가 갖고 있는 총 금액을 계산하는 등의 도메인 로직들은 분리를 해야하는거 아닌가?” 란 고민을 시작하게 됩니다.
도메인 객체라고 부르는 Order 객체가 너무 데이터베이스와 강결합인 것이죠. 특히 JPA 란 기술과 너무 뗄레야 뗄 수 없는 관계로 사용이 되고 있습니다.
OrderRepository 를 봐도 데이터에 접근하기 위한 리포지토리로 선언했는데 JpaRepository 를 상속받고 있으니 JPA 를 그만 쓰고 싶어도 JPA 가 너무 깊이 침투해버린 상황인 것이죠.
도메인 객체가 하위에 있는 인프라 레이어와 강한 의존관계를 가지며 JPA 기술에 너무 강결합이 심하다는 생각에 Hexagonal Architecture 가 나오기 시작했습니다.
Hexagonal Architecture 를 검색하면 아래와 같은 육각형 그림이 많이 나옵니다. (사실 육각형의 뜻이 있는 건 아니고, 양파 껍질 아키텍처 또는 포트와 어댑터 아키택처 등 이름이 되게 많습니다.)
그림을 보면 도메인 모델이라고 얘기하는 비즈니스 정책이 한 가운데 있고, 주위를 둘러싸고 있는 포트들과 포트에 연결하는 어댑터들이 있습니다.
그리고 외부 세계에는 클라이언트가 될 수도 있고 데이터베이스가 될 수도 있는데, 외부의 시스템들이 어댑터를 통해서 도메인 모델에 접근하는 것을 볼 수 있습니다.
여기서 핵심은 도메인 모델 자체가 가장 안쪽에 있다는 것입니다.
이 도메인 모델에 접근하기 위해서 어댑터와 포트라는 추상적인 것을 통하고 도메인 모델은 외부의 것을 전혀 모르는 것입니다.
즉, 도메인 모델이 JPA 기술을 아예 모르도록 설계할 수 있는 것이죠.
이게 어떻게 가능할까요?
DI 의 개념을 확장시켜서 활용하는 것입니다. 하나의 추상된 인터페이스를 두고 구현하는 구현체를 따로 두는 것이죠.
다시 이야기하면, 데이터 액세스를 하기 위한 리포지토리 인터페이스를 따로 두고 인터페이스를 구현하는 어떤 JPA 리포지토리를 따로 두어서 런타임 시점에 주입을 해준다면 실제 구현한 도메인 객체는 JPA 란 구현기술을 몰라도 될겁니다.
이런 설계에 대한 고민을 하는 것이 Hexagonal Architecture 라고 할 수 있습니다.
Layered Architecture 는 클라이언트 요청이 컨트롤러, 서비스, 도메인을 타고 들어오는 한쪽 방향의 모습을 보였는데 Hexagonal Architecture 은 도메인 모델을 중심으로 둘러싸고 있는 모습이란 차이점이 있습니다.
작은 시스템이라면 Layered Architecture 로 충분하겠죠.
하지만 이제 시스템이 커지고 멀티 모듈로 구성해서 모듈이 점점 많아지는게 예상이 된다면 Hexagonal Architecture 를 적용하는게 좋겠죠?