etc/study

[Architecture] '레이어드 아키텍처에서 인터페이스 잘 사용하면 그게 헥사고날 아키텍처 아닌가?'에 대한 의문을 해결해보자

만나쓰 2024. 10. 11. 16:43

0. Intro

"레이어드 아키텍처에서 인터페이스 잘 사용하면 그게 헥사고날 아키텍처 아닌가?"하는 의문을 해결하기 위해 이 글을 작성하게 되었다.

 

결론부터 얘기하자면 맞지만 다르다. 레이어드 아키텍처에서 OCP 원칙이 지켜지지 않는다는 단점을 헥사고날 아키텍처가 보완한다는 얘기가 있는데, 사실 계층별로 인터페이스를 잘 설계하고 추상화 한다면 DIP, OCP 원칙 모두 지킬 수 있다고 생각한다. 하지만, 아키텍처의 핵심 철학이 다르고, 이것 때문에 레이어드 아키텍처는 여러 문제점을 야기한다.

 

좀더 자세히 알아보자.

 

1. 레이어드 아키텍처, 그리고 문제점

레이어드 아키텍처에서는 상위 계층에서 하위 계층 방향으로 단방향 제어 흐름을 가진다. Presentation 계층은 Domain 계층에 의존하고, Domain 계층은 Persistence 계층에 의존하게 된다.

이런 레이어드 아키텍처에서는 각 계층 간의 역할 분리가 명확하지 않고, 계층을 분리하는 규칙 외 다른 규칙을 강제하기 어렵다. '계층'의 관점으로 설계된 프로젝트에서 DIP, OCP 원칙이 지속되기 어려우며, 나아가 아래 5가지 문제점이 있다.

 

1. 데이터베이스 주도 설계를 유도한다.
2. 지름길을 택하기 쉬워진다.
3. 테스트하기 어려워진다.
4. 유스케이스를 숨긴다. ('넓은 서비스 문제')
5. 동시 작업이 어려워진다.

 

위의 5가지 문제점은 '만들면서 배우는 클린 아키텍처'에 자세하게 설명하고 있으니, 생략한다. (잘 정리된 블로그도 많으니 참고하자.)

 

나는 5가지 문제중 "2. 지름길을 택하기 쉬워진다."가 가장 중요한 문제점이라고 생각한다. 나머지 문제들은 사실 지름길을 택하면서 발생하는 문제다. Controller -> Repository로 Service 계층을 생략한다거나, 상위 계층에 위치한 컴포넌트를 아래로 내려버리는 등의 '지름길을 선택하는 것이 가능하다'는 것이 문제다. 초반에는 계층별로 인터페이스를 잘 설계해서 DIP 원칙을 지키더라도, '강제성'이 없기 때문에 '깨진 유리창 이론'처럼 쉽게 깨지고 번지게 되는 것이다.

 

 

2. 헥사고날 아키텍처

헥사고날 아키텍처의 핵심은 비즈니스 로직을 외부 시스템과 철저히 분리하여 독립성을 높이고, 변경에 강한 유연한 시스템을 설계하는 것이다. 이를 위해 도메인 코드가 바깥으로 향하는 어떠한 의존성도 없어야 한다는 규칙을 가지고 있다. (== 계층 간의 모든 의존성이 코어 안쪽으로 향하게 해야 한다.)

 

레이어드 아키텍처는 각 계층이 아래의 계층에 직접적으로 의존하기 때문에, 모킹해야 할 대상이 많아지고 복잡해질 수 있다. 비즈니스 로직을 테스트할 때 데이터 액세스 계층뿐만 아니라 그 하위에 있는 시스템까지 고려해야 할 수 있기 때문이다.

반면, 헥사고날 아키텍처는 도메인 로직을 테스트할 때는 외부 의존성을 모킹하여, 해당 로직이 외부 환경에 독립적으로 잘 동작하는지 쉽게 검증 가능하다. 헥사고날 아키텍처는 도메인 로직이 외부 시스템과의 상호작용을 직접 담당하지 않으며, 이러한 상호작용은 어댑터에서 처리된다. 따라서 도메인 로직을 테스트할 때는 외부 의존성을 모킹하는 것이 훨씬 간단해진다. 

 

 

 

3. 결론

Q. "레이어드 아키텍처에서 인터페이스 잘 사용하면 그게 헥사고날 아키텍처 아닌가?"

A. "맞지만 아키텍처의 핵심 철학이 다르다."

 

레이어드 아키텍처는 계층 간 역할 분담을 통해 의존성을 관리하고, 상위 계층이 하위 계층에만 의존하는 구조를 강조하며, 헥사고날 아키텍처는 비즈니스 로직을 외부 시스템과 철저히 분리하여 독립성을 높이고, 변경에 강한 유연한 시스템을 설계하는 것이 핵심이다.

레이어드 아키텍처에서도 DIP, OCP 원칙을 지킬 수는 있으나, 깨지기 쉽다. 도메인 로직을 외부로부터 완전히 독립적으로 보호하고 싶다면 헥사고날 아키텍처를 고려해보자.