작성
·
1K
·
수정됨
3
최근에 제가 고민했던 부분의 토비님의 의견이 궁금해서 질문드립니다.
“계층형 아키텍처와 헥사고날 아키텍처는 정말 본질적으로 다른 걸까?”
예를 들어, 계층형 아키텍처에서도 인터페이스를 통해 상위 계층이 하위 계층을 의존하도록 설계하면 DIP(Dependency Inversion Principle)를 지킬 수 있습니다. 그렇게 하면 헥사고날 아키텍처가 지향하는 의존성 역전과 사실상 동일한 구조가 만들어지지 않을까요?
그렇다면 DIP를 잘 구현한 계층형 아키텍처는 헥사고날 아키텍처와 다르지 않다고도 볼 수 있을 것 같습니다. 이 생각대로라면, 우리가 그동안 “계층형 아키텍처”라고 부르며 개발하던 많은 구조들이 사실상 헥사고날 아키텍처였던 것 아닌가? 라는 생각도 들었습니다.
만약 두 아키텍처가 여전히 다르다고 본다면, 그 차이는 폴더 구조나 패키지 구성 방식처럼 물리적인 형태에서 오는 걸까요? 하지만 두 아키텍처 모두 논리적이고 추상적인 설계 철학을 이야기하는 것인데, 물리적 구조로만 구분하는 건 이상하다고 느껴집니다.
결국 저는, 잘 설계된 아키텍처라면 헥사고날이든 계층형이든 최종 목표는 동일하다, 라는 생각이 들었습니다.
즉, SRP(Single Responsibility Principle) 를 지키고,
외부 기술의 변화가 도메인에 영향을 주지 않아야 하며 (헥사고날),
persistence 계층이 바뀌더라도 핵심 비즈니스 로직은 변하지 않아야 한다 (계층형),
는 점에서 둘의 지향점은 같다고 느낍니다.
혹시 제가 놓치고 있는 중요한 관점이 있을까요?
토비님께서는 이 두 아키텍처를 어떻게 구분하시고, 어떤 기준을 중요하게 보시는지 궁금합니다.
답변 2
7
정말 좋은 질문을 해주셨네요. 저도 많은 생각을 했던 주제라 이런 걸 물어봐주시면 하고 싶은 얘기를 꺼낼 수 있어서 좋습니다. 다 얘기하자만 길어질 듯해서 몇 가지만 추려볼게요.
우선 계층형 아키텍처란 무엇이다라는 것에 모두가 다 동의할만한 명확한 정의나 제약조건 같은 게 선명하게 존재하지 않는다고 봅니다. 관심사에 따라 계층을 나누고, 계층간 의존/호출 구조는 단방형이어야 하고, 하위 계층의 인터페이스에만 의존한다, 정도만이 여러 계층형 아키텍처 설명에 공통적으로 나오는 설명이 아닐까 싶습니다.
그런데 말씀하신 DIP(의존관계 역전)는 계층형 아키텍처의 일반 규칙인 단방향 의존성, 의존역전 금지 제약조건의 위반입니다. 계층형 아키텍처를 전통적인 4개(또는 3개)의 순으로 배열하고 DIP를 적용해서 인프라 계층이 도메인 계층에 의존하는 구조로 그리면(DDD 책에 나오는 그림이죠) 그건 엄밀히 말해서 계층형 아키텍처가 아닙니다.
헥사고날 아키텍처는 당시 유행하던 4계층 계층형 아키텍처에 대한 대안으로 소개된 것입니다. 그 계층형 아키텍처에는 DIP가 없었습니다. 그래서 DIP까지 넣은 걸 굳이 계층형 아키텍처라고 부른다면, 헥사고날과 뭐가 다른가 따져보면 구조적으로 유사한 점이 많다고 할 수는 있습니다. 아무튼 계층형 아키텍처가 뭘 말하는지, 어떤 것이 계층형인지를 명확하게 하지 않고 이야기하면 한없이 복잡해지죠.
그런데 아키텍처도 그렇고 디자인 패턴도 그렇고, 구조가 핵심은 아닙니다. 객체지향 디자인 패턴을 보면 대부분 구조가 피슷합니다. 특히 오브젝트 스코프인 경우 대부분 합성을 이용하기 때문에 다이어그램만 그려놓고 보면 그게 그거 같죠. 하지만 각 패턴은 다릅니다. 왜냐하면 의도(Intention)이 다르기 때문입니다. 그리고 그걸로 풀고자 하는 문제가 다르죠. 솔루션의 구조가 비슷하다고 같은 패턴이 아니듯. DIP가 적용된 계층형 아키텍처(이건 모순이긴 하지만)와 헥사고날이 비슷하게 생겼으니까 결국 그게 그거 아닌가라고 하면, 저는 다르다고 하겠습니다. 근본적으로 아키텍처 스타일을 적용할 때 의도하고 지향하는 목적이 다르기 때문입니다. 헥사고날은 대칭성에 주목하고 안과 밖으로 구분했습니다. 그리고 그 내부는 어떤 구조이든 관심이 없습니다. 강의에서 제가 도메인 계층이 없어도 헥사고날이라고 할 수 있다고 했죠. 도메인 계층이 존재하고 도메인 도멜 패턴을 쓰는지는 헥사고날 아키텍처 자체와 무관합니다. 그렇게만 보면 헥사고날 아키텍처는 2계층인가라고 생각할 수도 있는데, 근본적으로 계층형 아키텍처와 계층에 대한 개념과 설명이 다르기 때문에 그렇게 말할 수 없습니다. 물론 헥사고날을 비대칭성을 강조해서 설명하면 driving, driven으로 풀어놓고 3계층으로 설명할 수도 있지만, 그게 헥사고날 아키텍처의 주요 관심사는 아니거든요.
그래서 헥사고날 아키텍처의 설계 의도를 따라 그 목적을 충족한 뒤에 아키텍처를 더 확장할 수 있습니다. 이번 강의에서 도메인 모델 패턴을 적용하면서 도메인 계층을 추가하자고 한 것이고, 그건 헥사고날 아키텍처에서 허용된 작업이므로, 결과적으로 확장된 헥사고날 아키텍처가 된 것이죠. 그러면서 대칭성으로 보자면 3계층으로 볼 수도 있다고 설명 드린 것이고요. 비대칭성으로 보자면 4계층처럼 보일 수도 있습니다. 이미 계층형 아키텍처의 전형적인 구성과는 다르죠.
그런데 DIP를 진지하게 적용해보면, 결국 비슷한 결과가 나오는게 아닌가라는 생각을 하기도 합니다. 그래서 DIP가 적용된 계층형 아키텍처라는 관점으로 이야기를 할 수 있긴한데요. 다시 말씀드리지만 DIP를 기존 계층형 구조에 적용하면 계층형 아키텍처가 아니게 됩니다. 사용 흐름은 단방향이나 코드의 의존성이 역적됐기 때문에 계층 구조 위반이거든요.
그런데 이걸 계층형 아키텍처의 원칙을 그대로 지키도록 만드는 방법이 있습니다. DIP 적용으로 의존성 방향이 역전된 것을 풀어서 다시 단방향 구조로 그려보면 됩니다. 그걸 잘 설명한 사람이 DDD 관련 책을 쓴 본 버논이고요. 그의 책에 다음과 같은 그림을 보여줍니다. 계층형 아키텍처에 DIP를 적용하면 다음과 같은 그림을 그려야 맞는 겁니다.
<Implementing Domain Driven Design - Figure 4.3>
그리고 여기서 애플리케이션의 내부와 외부를 port와 adapter를 통해서 분리하고 의존하게 만드는 그림을 그리면, 위의 그림을 삥 돌려보면 우리가 많이 보는 헥사고날 아키텍처가 됩니다.
근본적으로 헥사고날 아키텍처의 관심과 의도가 있습니다. 우리가 뭐뭐 아키텍처라고 부르긴 하지만 그게 전체 아키텍처를 딱 정하는 것은 아닙니다. 저는 아키텍처 패턴이라고 부르는 게 더 자연스럽다고 봅니다. 그런면에서 하나 이상의 아키텍처 패턴이 적용될 수 있습니다. CQRS도 아키텍처 패턴인데, 헥사고날 아키텍처를 따라서 만든 아키텍처에 CQRS 아키텍처 패턴을 적용할 수 있죠. 마찬가지로 계층형 아키텍처가 지지하고 의도한 바를 적용하고 그에 대해 관심을 기울인다면 헥사고날 아키텍처에 계층형 구조를 더 강화할 수 있습니다. 이번 강의의 최종 아키텍처가 그런 결과물이죠.
그래서 그 두 가지를 구분해서 하나를 선택하거나 차이를 부각하거나 하기 보다는 아키텍처의 더 근본적인 의도와 그게 가져오는 영향을 살펴보면서 특성을 파악하고, 현재 개발하는 시스템의 목적에 맞도록 이를 적용하는 것이 바람직할 겁니다.
설명이 됐기를 바라면서 일단 이 정도로 설명 드릴게요. 깊이 생각해보시고, 그래도 더 궁금하신 게 있으면 또 질문 주세요.
1
SRP는 객체지향 설계원칙으로 소개된 것인데, 기본 정의 자체가 모듈에 대한 것이죠. 계층도 하나의 모듈이라고 할 수 있으니 SRP도 중요할 겁니다. 하지만 그게 유일한 목표라고 할 수는 없죠. SRP는 프로그래밍의 거의 모든 대상에 적용 가능할 겁니다. 소프트웨어의 기본 원칙인 높은 응집도와 낮은 결합도의 가장 기본적인 적용이기 때문이죠.