잘 만들어진 계층형 아키텍처는 선택의 폭을 넓히고, 변화하는 요구사항과 외부 요인에 빠르게 적응할 수 있게 해준다.
일반적으로 로직 flow와 컴포넌트들의 의존성 flow가 일치하여 받아들이기 쉽다.
전통적인 계층형 아키텍처의 토대는 데이터베이스
따라서 모든 것이 결국은 영속성 계층을 토대로 만들어진다.
하지만 우리가 만드는 대부분의 애플리케이션은 상태가 아니라 행동을 중심으로 모델링한다.
하지만 계층형 아키텍처는 데이터베이스의 구조를 먼저 생각하고, 이를 토대로 도메인 로직을 구현하게 하는 데이터 중심적 사고를 유발한다.
비즈니스 관점에서는 전혀 맞지 않는 방법이다.
이런 데이터베이스 중심적인 아키텍처가 만들어지는 가장 큰 원인은 → ORM
ORM에 의해 관리되는 엔티티들은 일반적으로 영속성 계층에 위치
즉 위 그림과 같은 영속성 계층과 도메인 계층 사이에 강한 결합이 발생!
서비스는 이로 인해, 영속성 계층과 관련된 작업들을 해야만 한다.
영속성 코드가 사실상 도메인 코드에 침투하여 둘 중 하나만 바꾸는 것이 어려워진다!
전통적인 계층형 아키텍처에서 전체적으로 적용되는 유일한 규칙 → 특정 계층에서는 같은 계층에 있는 컴포넌트와 아래에 있는 계층에만 접근 가능
만약 상위 계층에 위치한 컴포넌트에 접근해야 한다면?
이런 상황이 쌓이며... 아래와 같은 그림의 현상 발생
현재 상황에서 의존성 방향의 끝이며 변경하기 어려운 안정적인 컴포넌트여야하는 영속성 layer가 비대해지며 변경될 일(이유)이 많아지는 모순적인 일이 발생!
변경하기도 힘들고 그로인해 부수효과가 얼마나 생길지 가늠조차 안되는 상태인데 계속 해서 변경해야하는 답도 없는 상황 발생...
계층형 아키텍처에서는 계층을 건너뛰는 현상이 발생하기도...
이것도 처음에는 편하고 좋아 보인다...
결국 크게 2가지 문제가 발생
개발자들은 사실상 새로운 코드를 짜는데 시간을 쓰기보다는 기존 코드를 바꾸는 데 더 많은 시간을 할애한다.
아키텍처는 코드를 빠르게 탐색하는데 도움이 돼야 한다.
위에서 이야기했던 것처럼, 계층형 아키텍처는 도메인 로직이 여러 계층에 걸쳐 흩어지기 쉽다!
계층형 아키텍처는 도메인 서비스의 ‘너비’에 관한 규칙을 강제하지 않는다.
즉 위처럼 아주 넓은 서비스가 만들어질 수 있다. (이 부분은 계층형 아키텍처가 아니라 뒤에 나오는 아키텍처에서도 주의하고 신경써야할 부분이라 생각한다.)
넓은 서비스 → 코드 상에서 특정 유스케이스를 찾기 어렵다!
고도로 특화된 좁은 도메인 서비스가 유스케이스 하나씩만 담당해야..!! (UserService → RegisterUserService)
난 사실 이 네이밍을 선호하지 않는다.
이 네이밍 자체가 서비스의 너비를 넓히고, 많은 책임을 섞이게 만든다고 생각한다. 너무 넓은 범위를 아우르기 쉬운 네이밍인 것 같다.→ 이 부분에 대해서 고도로 특화된 좁은 도메인 서비스 네이밍을 잘하면 해결된다고 생각할수도 있을 것 같다.
위 처럼 고도로 특화된 좁은 도메인 서비스가 필요하다는 개념이 잡히지 않은 개발자가 팀의 합류한다면? 그 사람이 과연 Service라는 네이밍이 붙은 클래스를 보며 무슨 생각을 할까?
일반적으로 프로젝트에 인원이 더 투입될수록 더 빠른 속도를 기대한다.
하지만, 아키텍처가 동시 작업을 지원하는 것은 쉽지 않은 일이다.
계층형 아키텍처에서 계층별로 맡아서 작업하기란 쉽지 않다. 모든 것이 영속성 계층 위에 만들어지기 때문에 아래 계층의 개발이 선행되어야한다.
그렇기에 특정 기능은 동시에 한 명의 개발자만 작업할 수 있다.
인터페이스를 이용하면 되지 않은가?
또한 코드에 넓은 서비스가 존재한다면, 서로 다른 기능을 동시에 작업하기가 더욱 어려워진다.
계층형 아키텍처는 많은 것들이 잘못된 방향으로 흘러가도록 용인
엄격한 자기 훈련 없이는 시간이 지날수록 코드 품질이 저하되고 유지보수하기 어려워진다.
계층형 아키텍처의 함정을 염두하면, 유지보수하기에 더 쉬운 솔루션을 만드는 데 도움이 될 것이다!