소프트웨어를 계층으로 분리하고 의존성 규칙을 준수한다면 본질적으로 테스트하기 쉬운 시스템을 만들게 될 것이며, 그에 따른 이점을 누릴 수 있다.
데이터베이스나 웹 프레임워크와 같은 시스템의 외부 요소가 구식이 되더라도, 이들 요소를 야단스럽지 않게 교체할 수 있다.
클린 아키텍처
- 육각형 아키텍처 ( = 포트와 어댑터) : 앨리스터 코오번(Alistair Cockburn)이 개발했음
- DCI (Data, Context and Interaction) : 제임스 코플리언과 트리그베 린스쿠주가 만들었음
- BCE(Boundary-Control-Entity) : 이바 야콥슨이 자신의 저서인 Object Oriented Software Engineering>에서 소개함
위 아키텍처는 세부적인 면에서 다소 차이가 있더라도 그 내용은 상당히 비슷하다. 목표가 모두
관심사의 분리
다.각 아키텍처는 최소한 업무 규칙을 위한 계층 하나와, 사용자와 시스템 인터페이스를 위한 또 다른 계층 하나를 반드시 포함한다.

시스템이 갖게 되는 특징
- 프레임워크 독립성 : 아키텍처는 다양한 기능의 라이브러리를 제공하는 소프트웨어, 즉 프레임워크의 존재 여부에 의존하지 않는다.
- 테스트 용이성 : 업무 규칙은 UI, 데이터베이스, 웹 서버, 또는 여타 외부 요소가 없이도 테스트할 수 있다.
- UI 독립성 : 시스템의 나머지 부분을 변경하지 않고도 UI를 쉽게 변경할 수 있다.
- 데이터베이스 독립성 : 오라클이나 MS SQL 서버를 몽고DB, 빅테이블, 카우치DB 등으로 교체할 수 있다. 업무 규칙은 데이터베이스에 결합되지 않는다.
- 모든 외부 에이전시에 대한 독립성. 실제로 업무 규칙은 외부 세계와의 인터페이스에 대해 전혀 알지 못한다.
의존성 규칙
- 위 그림에서 각각의 동심원은 소프트웨어에서 서로 다른 영역을 표현한다. 보통 안으로 들어갈수록 고수준의 소프트웨어가 된다. 바깥쪽 원은 메커니즘이고 안쪽 원은 정책이다.
의존성 규칙 : 소스 코드 의존성은 반드시 안쪽으로, 고수준의 정책을 향해야 한다.
- 내부의 원에 속한 요소는 외부의 원에 속한 어떤 것도 알지 못한다. 특히 내부의 원에 속한 코드는 외부의 원에 선언된 어떤 것에 대해서도 그 이름을 언급해서는 절대 안된다.
- 같은 이유로 외부의 원에 선언된 데이터 형식도 내부의 원에서 절대로 사용해서는 안 된다. 특히 그 데이터 형식이 외부의 원에 있는 프레임워크가 생성한 것이라면 더더욱 사용해서는 안 된다.
- 우리는 외부 원에 위치한 어떤 것도 내부의 원에 영향을 주지 않기를 바란다.
엔티티
- 엔티티는 전사적인 핵심 업무 규칙을 캡슐화한다. 엔티티는 메서드를 가지는 객체이거나 일련의 데이터 구조와 함수의 집합일 수도 있다.
- 전사적이지 않은 단순한 단일 애플리케이션을 작성하고 있다면 엔티티는 해당 애플리케이션의 업무 객체가 된다.
유스케이스
- 유스케이스 계층의 소프트웨어는 애플리케이션에 특화된 업무 규칙을 포함한다.
- 이 계층에서 발생한 변경이 엔티티에 영향을 줘서는 안 된다. 또한 데이터베이스, UI, 또는 여타 공통 프레임워크와 같은 외부 요소에서 발생한 변경이 이 계층에 영향을 줘서도 안 된다. 유스케이스 계층은 이러한 관심사로부터 격리되어 있다.
- 하지만 운영 관점에서 애플리케이션이 변경된다면 유스케이스가 영향을 받으며, 따라서 이 계층의 소프트웨어에도 영향을 줄 것이다. 유스케이스의 세부사항이 변하면 이 계층의 코드 일부는 분명 영향을 받을 것이다.
인터페이스 어댑터
- 어댑터는 데이터를 유스케이스와 엔티티에게 가장 편리한 형식에서 데이터베이스나 웹 같은 외부 에이전시에게 가장 편리한 형식으로 변환한다.
- 이 계층은 예를들어 GUI의 MVC 아키텍처를 모두 포괄한다. 프레젠터, 뷰, 컨트롤러는 모두 인터페이스 어댑터 계층에 속한다.
- 마찬가지로 이 계층은 데이터를 엔티티와 유스케이스에게 가장 편리한 형식에서 영속성 용으로 사용 중인 임의의 프레임워크(즉, 데이터베이스)가 이용하기에 가장 편리한 형식으로 변환한다. 이 원 안에 속한 어떤 코드도 데이터베이스에 대해 조금도 알아서는 안 된다.
- 또한 이 계층에는 데이터를 외부 서비스와 같은 외부적인 형식에서 유스케이스나 엔티티에서 사용되는 내부적인 형식으로 변환하는 또 다른 어댑터가 필요하다.
프레임워크와 드라이버
- 가장 바깥쪽 계층은 일반적으로 데이터베이스나 웹 프레임워크 같은 프레임워크나 도구들로 구성된다.
- 일반적으로 이 계층에서는 안쪽 원과 통신하기 위한 접합 코드 외에는 특별히 더 작성해야 할 코드가 그다지 많지 않다.
- 프레임워크와 드라이버 계층은 모든 세부사항이 위치하는 곳이다. 웹과 데이터베이스는 세부사항이다.
- 이러한 것들을 모두 외부에 위치시켜 피해를 최소화한다.
경계를 횡단하는 데이터는 어떤 모습인가
- 경계를 가로지르는 데이터는 흔히 간단한 데이터 구조로 이루어져 있다. 중요한 점은 격리되어 있는 간단한 데이터 구조가 경계를 가로질러 전달된다는 사실이다.
- 꾀를 부려서 엔티티 객체나 데이터베이스의 행을 전달하는 일은 원치 않는다. 우리는 데이터 구조가 어떤 의존성을 가져 의존성 규칙을 위배하게 되는 일은 바라지 않는다.
- 예를 들어 많은 데이터베이스 프레임워크는 쿼리에 대한 응답으로 사용하기 편리한 데이터 포맷을 사용한다. 이러한 포맷은 ‘행(row) 구조’인 경우가 많다. 이 행 구조가 경계를 넘어 내부로 그대로 전달된다면 내부의 원에서 외부 원의 무언가를 알아야 하기에 의존성 규칙을 위배하게 되는 것이다.
- 따라서 경계를 가로질러 데이터를 전달할 때, 데이터는 항상 내부의 원에서 사용하기에 가장 편리한 형태를 가져야만 한다.
