02. 의존성 역전하기
단일 책임 원칙
하나의 컴포넌트는 오로지 한 가지 일만 해야 하고, 그것을 올바르게 수행해야 한다.
- ‘단일 책임 원칙’은 위와 같은 정의로 알고 있을텐데 실제 정의는 아래와 같다.
컴포넌트를 변경하는 이유는 오직 하나뿐이어야 한다.
- ‘책임’은 ‘한 가지 일만 하는 것’보단 ‘변경할 이유’로 해석해야 한다.
- 만약 컴포넌트를 변경할 이유가 한 가지라면 어떤 다른 이유로 소프트웨어를 변경하더라도 이 컴포넌트에 대해 신경 쓸 필요가 전혀 없다.
- 하지만 ‘변경할 이유’는 컴포넌트 간 의존성을 통해 너무 쉽게 전파된다.
- 아무것도 의존하고 있지 않은 컴포넌트는 자신의 ‘변경할 이유’에만 신경쓰면 된다.
- 다른 많은 컴포넌트를 의존하고 있는 컴포넌트는 다른 컴포넌트들의 ‘변경할 이유’에 영향 받아 함께 변경되어야 한다.
- 시간이 지날수록 컴포넌트를 변경할 더 많은 이유가 쌓이게 된다.
부수 효과에 관한 이야기
- 한 컴포넌트가 의존하고 있는 다른 컴포넌트의 변경에 영향을 받아 나타나는 일을 ‘부수효과’라고 한다.
- 복잡한 소프트웨어에선 핵심 컴포넌트의 변경으로 발생할 ‘부수효과’ 때문에 소프트웨어 변경을 두려워하는 일이 많다.
- 즉 잘못 구조화된 소프트웨어를 변경하는 데는 많은 비용이 지불된다.
의존성 역전 원칙
- 계층형 아키텍처에서 계층 간 의존성은 항상 다음 계층인 아래 방향을 가리킨다.
- 때문에 영속성 계층을 변경할 때 잠재적으로 도메인 계층도 변경해야 한다.
- 영속성 코드가 변경되어도 도메인 코드는 바꾸고 싶지 않다.
- 의존성 역전을 사용하면 의존성의 방향을 역전시킬 수 있다.
클린 아키텍처
- 로버트 C. 마틴은 ‘클린 아키텍처’에서 도메인 코드가 바깥으로 향하는 어떤 의존성도 없어야 한다고 말한다.
- 바깥 - 프레임워크, 데이터베이스, UI 기술, 그 밖의 외부 애플리케이션이나 인터페이스
- 아키텍처의 코어에는 유스케이스와 도메인 엔티티가 있다.
- 유스케이스는 서비스라고도 부르는데 단일 책임을 갖기 위해 더 세분화 되어 있다. (넓은 서비스 문제 해결을 위해)
- 코어 주변으로 비즈니스 규칙을 지원하는 다른 모든 컴포넌트를 확인할 수 있다.
- 도메인 코드에선 특정 프레임워크에 특화된 코드로부터 자유로워지고 도메인 주도 설계를 가장 순수한 형태로 적용해볼 수도 있다.
- JPA 영속성이나 UI 특화 문제를 해결할 수 있다.
- 하지만 도메인, 영속성, UI 같은 외부 계층과 철저한 분리를 위해 엔티티에 대한 모델을 각 계층에서 유지보수 해야 한다.
- ex) 도메인 계층의 엔티티와 영속성 계층의 JPA 엔티티가 분리되어 각 계층에서 관리되어야 한다.
- 도메인과 영속성이 데이터를 주고 받을 때 각 엔티티로의 변환 작업이 추가된다.
육각형 아키텍처 (헥사고날 아키텍처)
- 헥사고날 아키텍처는 클린 아키텍처의 원칙들을 조금 더 구체적으로 만들어준다.
- 아래처럼 애플리케이션 코어가 육각형으로 표현되어 있어 붙여진 이름
- 육각형 안에는 도메인과 유스케이스가 있고 바깥으로 향하는 의존성은 없다.
- 육각형 바깥에는 애플리케이션과 상호작용하는 다양한 어댑터가 있다.
- ex) 웹 브라우저, 데이터베이스 등과 상호작용하는 어댑터
- 왼쪽에 있는 어댑터들은 코어를 호출하는 애플리케이션을 주도하는 어댑터들이다.
- 오른쪽에 있는 어댑터는 코어에 의해 호출되는 애플리케이션에 의해 주도되는 어댑터들이다.
- 위와 같은 핵심 개념으로 포트와 어댑터 아키텍처로도 알려져 있다.