계층형 아키텍처의 문제와 의존성 역전
계층형 아키텍처의 문제
웹 계층, 도메인 계층, 영속성 계층으로 구성된 전통적인 계층형 아키텍처는 코드에 나쁜 습관이 스며들기 쉽게 만들고, 시간이 지날수록 변경이 어려워지도록 만든다.
ORM 프레임워크를 사용하게 되면서 서비스 로직이 Entity, Repository등에 의존하게 되어 데이터베이스 주도 설계를 유도한다.
특정 계층은 같은 계층의 컴포넌트나 아래 계층만 접근가능하지만, 상위 컴포넌트에 접근하기 위해 아예 하위 컴포넌트를 상위 계층으로 올려버리는 만행을 쉽게 저지를 수 있다.
기능을 추가하거나 변경할 적절한 위치를 찾는 일이 빈번한데, 계층형 아키텍처는 도메인 로직이 여러 계층에 흩어지기 쉽다.
하나의 서비스에 비대한 양의 유스케이스가 존재하게 되어 영속성 계층에 많은 의존성을 갖게된다. 의존성이 많이 엮이면 서비스를 테스트하기도 어려워진다.
단일 책임 원칙
컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다.
널리 알려져있는 의미는 하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 올바르게 수행해야 한다 라는 것이지만, 결국 변경할 이유가 하나뿐이라면 자연스레 한 가지의 일만 하게 된다.
변경할 이유는 컴포넌트 간의 의존성을 통해 쉽게 전파되므로, 컴포넌트 간의 의존성을 최소화하는 것이 중요하다!
의존성 역전
코드상의 어떤 의존성이든 방향을 역전시킬 수 있다는 법칙이다.
의존성의 양쪽 코드를 모두 제어 가능한 경우에만 의존성 역전이 가능하다.
즉, 서드파티 라이브러리에 의존하는 경우 의존성 역전이 불가능하다.
도메인과 영속성의 의존성 역전 예제
도메인 계층의 엔티티와 영속성 계층의 엔티티를 구분한다.
도메인 계층에 리포지토리 인터페이스를 도입해 영속성 계층이 도메인 계층을 의존하도록 해 의존성을 역전시킨다.
인터페이스를 작성할 때는 클라이언트가 필요로 하는 메서드를 기반으로 분리해야 한다.
인터페이스의 이름, 메서드 이름을 정할 때도 구체적인 클래스의 이름을 드러내지 않는 것이 중요
클린 아키텍처
클린 아키텍처에서 모든 의존성은 도메인 로직을 향해 안쪽 방향으로 향한다.
계층 간의 모든 의존성은 안으로 향해야 한다.
이로써 도메인 코드에서는 어떤 영속성 프레임워크나 UI 프레임워크를 사용하는지 알 수 없어 비즈니스 규칙에 집중하여 자유롭게 모델링할 수 있다.
헥사고날 아키텍처
헥사고날 아키텍처는 어떤 프레임워크, 기술을 사용하는지에 의존하지 않고 도메인을 중심으로 개발할 수 있도록 해준다.
도메인 엔티티에는 도메인의 정보들이 담긴다.
유스케이스는 도메인 엔티티와 상호작용하며 비즈니스 로직을 수행한다.
포트와 어댑터
좌측의 어댑터는 애플리케이션 코어를 호출해 애플리케이션을 주도하는 어댑터이다.
우측의 어댑터들은 애플리케이션 코어에 의해 호출되어 애플리케이션에 의해 주도되는 어댑터이다.
애플리케이션 코어가 입력, 출력 포트를 제공해야 어댑터와 통신이 가능하다.
주도하는 어댑터의 입력 포트는 코어의 유스케이스 클래스 중 하나에 의해 구현된다.
주도되는 어댑터의 출력 포트는 코어에 의해 호출되는 인터페이스가 되고, 이 출력 포트를 어댑터가 구현한다.
추가 자료
주니어 개발자의 클린 아키텍처 맛보기 | 우아한형제들 기술블로그
https://lkic1625.github.io/architecture/hexagonal_architecture/
Last updated