다양한 아키텍처의 공통적인 목표는 관심사의 분리 이다.
- 계층으로 분리하여 관심사를 분리한다.
- 각 아키텍처는 최소한 업무 규칙을 위한 계층 하나와, 사용자와 시스템 인터페이스를 위한 또 다른 계층 하나를 반드시 포함한다.
아키텍처들은 모두 시스템이 다음과 같은 특징을 지니도록 만든다.
-
프레임워크 독립성
아키텍처는 프레임워크의 존재 여부에 의존하지 않는다. 이를 통해 프레임워크가 지닌 제약사항안으로 시스템을 욱여 넣는게 아닌 프레임워크를 도구로 사용할 수 있다.
-
테스트 용이성
업무 규칙은 UI, 데이터베이스, 웹 서버, 외부 요소 없이 테스트할 수 있다.
-
UI 독립성
시스템의 나머지 부분을 변경하지 않고도 UI를 쉽게 변경할 수 있다. 예를 들어 업무 규칙을 변경하지 않고도 웹 UI를 콘솔 UI로 대체할 수 있다.
-
데이터베이스 독립성
오라클이나 MS SQL서버를 몽고DB(MongoDB), 빅테이블(BigTable), 카우치DB(CauchDB) 등으로 교체할 수 있다. 업무 규칙은 데이터베이스에 결합되지 않는다.
-
모든 외부 에이전시에 대한 독립성
실제로 업무 규칙은 외부 세계와의 인터페이스에 대해 전혀 알지 못한다.
- 위 다이어그램은 아키텍처들 전부를 실행 가능한 하나의 아이디어로 통합하려는 시도다.
📕 의존성 규칙
위 그림에서
- 안으로 향할수록 고수준의 소프트웨어가 된다.
- 바깥쪽 원은 메커니즘이고, 안쪽 원은 정책이다.
이러한 아키텍처가 동작하도록 하는 가장 중요한 규칙은 의존성 규칙이다.
소스 코드 의존성은 반드시 안쪽으로, 고수준의 정책을 향해야 한다.
- 내부의 원에 속한 요소는 외부의 원에 속한 어떤 것도 알지 못한다.
- 함수, 클래스, 변수, 소프트웨어 엔티티로 명명되는 모든 것을 언급해선 안된다.
- 외부의 원에 선언된 데이터 형식도 내부의 원에서 절대로 사용해서는 안 된다.
📍 엔티티
- 전사적인 핵심 업무 규칙을 캡슐화
- 전사적이지 않고 단순한 애플리케이션을 작성한다면 엔티티는 해당 애플리케이션의 업무 객체가 된다.
- 운영 관점에서 특정 애플리케이션에 무언가 변경이 필요하더라도 엔티티 계층에는 절대로 영향을 주어서는 안 된다.
📍 유스케이스
- 애플리케이션에 특화된 업무 규칙을 포함하며 모든 유스케이스를 캡슐화하고 구현한다.
- 엔티티로 들어오고 나가는 데이터 흐름을 조정
- 엔티티가 자신의 핵심 업무 규칙을 사용해서 유스케이스의 목적을 달성하도록 이끈다.
- 이 계층에서 발생한 변경이 엔티티에 영향을 주면 안 되며, 외부 요소에서 발생한 변경이 이 계층에 영향을 주면 안된다.
- 관심사로부터 격리되어있다.
- 하지만 운영 관점에서 애플리케이션이 변경된다면 유스케이스가 영향을 받고, 따라서 이 계층의 소프트웨어에도 영향을 줄 것이다.
📍 인터페이스 어댑터
- 일련의 어댑터들로 구성
- 어댑터는 데이터를 유스케이스와 엔티티에게 가장 편리한 형식에서 데이터베이스나 웹 같은 외부 에이전시에게 가장 편리한 형식으로 변환
- 데이터를 엔티티와 유스케이스에게 가장 편리한 형식에서 영속성용으로 사용 중인 임의의 프레임워크가 이용하기에 가장 편리한 방식으로 변환
- 데이터를 외부 서비스와 같은 외부적인 형식에서 유스케이스나 엔티티에서 사용되는 내부적은 형식으로 변환하는 또 다른 어댑터가 필요
📍 프레임워크와 드라이버
- 데이터베이스나 웹 프레임워크 같은 프레임워크나 도구들로 구성
- 일반적으로 이 계층에는 안쪽원과 통신하기 위한 코드 외에 특별히 작성할 코드가 많지 않다.
- 세부사항이 위치하는 곳
- 외부에 위치시켜 피해를 최소화
📍 원은 네 개여야만 하나?
- 그럴필요는 없지만 항상 의존성 규칙은 적용된다.
- 소스코드 의존성은 안쪽을 향한다.
- 안쪽으로 갈수록 추상화와 정책의 수준은 높아진다.
- 가장 바깥쪽 원은 저수준의 구체적인 세부사항으로 구성된다.
- 가장 안쪽 원은 가장 범용적이며 높은 수준을 가진다.
📍 경계 횡단하기
- 제어흐름과 의존성의 방향이 명백히 반대여야 하는 경우, 보통 의존성 역전 원칙을 사용하여 해결
- 아키텍처 경계를 횡단할 때도같은 기법을 사용할 수 있다.
- 동적 다형성을 이용하여 소스 코드 의존성을 제어흐름과 반대로 만들 수 있고, 이를 통해 제어흐름이 어느 방향으로 흐르든 상관 없이 의존성 규칙을 준수할 수 있다.
📍 경계를 횡단하는 데이터는 어떤 모습인가
- 경계를 가로지르는 데이터는 흔히 간단한 데이터 구조로 이루어져 있다.
- 격리되어 있는 간단한 데이터 구조가 경계를 가로질러 전달된다는 사실이다.
- 데이터 구조가 어떤 의존성을 가져 의존성 규칙을 위배하게 되는 일은 바라지 않는다.
- 따라서 경계를 가로질러 데이터를 전달할 때, 데이터는 항상 내부의 원에서 사용하기에 가장 편리한 형태를 가져야만 한다.
📗 전형적인 시나리오
의존성 방향에 주목하라.
모든 의존성은 경계선을 안쪽으로 가로지르며, 따라서 의존성 규칙을 수행한다.
📙 결론
소프트웨어를 계층으로 분리하고 의존성 규칙을 준수하면 본질적으로 테스트하기 쉬운 시스템을 만들게 되며, 시스템의 외부 요소가 구식이 되더라도 쉽게 교체할 수 있다.
📚 Reference
- Clean Architecture : 소프트웨어 구조와 설계의 원칙