클린 아키텍처
관심사 분리
- 소프트웨어를 계층으로 분리함으로써 관심사의 분리라는 목표를 달성할 수 있다.
- 최소한의 업무 규칙을 위한 계층 하나와 사용자와 시스템 인터페이스를 위한 또 다른 계층 하나를 반드시 포함한다.
분리된 아키텍처 시스템의 특징
- 프레임워크 독립성
- 프레임워크의 존재 여부에 의존하지 않는다.
- 테스트 용이성
- UI, DB, 웹 서버 등의 외부 요소 없이도 테스트가 가능하다.
- UI 독립성
- 시스템을 변경하지 않고도 UI를 쉽게 변경할 수 있다.
- 데이터베이스 독립성
- 기존 DB 서버를 다른 DB로 교체할 수 있다.
- 모든 외부 에이전시에 대한 독립성
- 외부 세계와의 인터페이스에 대해 전혀 알지 못한다.
의존성 규칙
저수준 계층의 변경, 코드 등이 고수준 계층에 영향을 줘서는 안된다.

- 위 그림은 실행가능한 하나의 아이디어로 통합하려는 시도이다.
- 보통 안쪽으로 들어갈수록 고수준 수프트웨어가 된다.
- 바깥쪽 원은 메커니즘이고 안쪽 원은 정책이다.
- 내부의 원에 속한 요소는 외부의 원에 속한 어떤 것도 알지 못한다.
- 외부 원에 위치한 어떤 것도 내부의 원에 영향을 주지 않아야한다.
엔티티
- 엔티티는 전사적인 핵심 업무 규칙을 캡슐화한다.
- 메서드를 가진 객체
- 일련의 데이터 구조
- 함수의 집합
- 전사적이지 안흔 단일 애플리케이션의 엔티티는 업무객체가 된다.
- 일반적이고 고수준의 규칙을 캡슐화한다.
유스케이스
- 애플리케이션에 특화된 업무 규칙을 포함한다.
- 엔티티로 들어오고 나가는 데이터 흐름을 조정한다.
- 변경이 발생하면 엔티티에 영향을 줘선 안된다.
- 또한 외부 요소이 변경이 된다면 이 계층에 영향을 받지 않아야한다.
인터셉터 어댑터????
- 데이터를 DB나 웹 같은 외부 에이전시에게 편리한 형식으로 변환한다.
- MVC 아키텍처를 모두 포괄한다. (프레젠터, 뷰, 컨트롤러)
- 영속성용으로 사용 중인 임의의 프레임워크가 이용하기 편리한 형식으로 변환한다.
프레임워크와 드라이버
- 안쪽원과 통신하기 위한 접합 코드가 작성된다.
- 이 외 추가적인 코드가 많지 않다.
- 모든 세부사항이 위치한 곳이다.
- 웹, 데이터베이스
- 외부에 위치시켜서 피해를 최소화한다.
원은 4개만??
- 많은 원이 필요한 경우도 있다
- 어떤한 경우든 의존성 규칙이 적용된다.
- 바깥쪽 원 : 저수준의 구체적인 세부사항 (구현체)???
- 안쪽 원 : 고수준의 추상화된 정책들을 캡슐화, 가장 범용적이다. (인터페이스)
경계 횡단하기
- 원의 경계를 횡단하는 방법 예시

- 컨트롤러와 프레젠터가 유스케이스와 통신하는 모습
- 주목할 부분
- 제어흐름
- 의존성 방향과 반대의 경우 DI 원칙을 사용하여 해결
- 소스 코드 의존성
- 유스케이스 == 인터페이스??
- 프레젠터 == 구현체???
- 경계 횡단하는 방법
- 동적 다형성을 사용하여 의존성과 제어흐름의 방향을 반대로 만들어 의존성 규칙을 준수할 수 있도록 한다.
경계를 횡단하는 데이터는 어떤 모습인가?
기본적인 구조체나 DTO 등을 원하는 데로의 모습을 볼 수 있다. 또는 파라미터로 전달할 수 있다. 그게 아니라면 해시맵으로 묶거나 객체로 구성할 수도 있다.
중요한 점은 격리되어 있는 데이터 구조가 경계를 가로질러 전달된다는 점이다.
엔티티 객체나 db의 데이터를 바로 전달하지 않는다. 이유는 의존성 규칙을 위배되는 일이기 때문이다.
⇒ 내부 계층에서는 외부계층을 알 수 없다.
전형적인 시나리오

- 이 그림대로라면 input과 output관련한 것들이 use case에 속하는 걸까요??
- 계층별로 방향은 안쪽으로 향해야하는 것으로 이해했는 데 이 그림에서 interface와 usercaseInteractor는 왜 반대 방향의 화살표를 가르킬까요?
- 그럼 경계를 나누는 기준은 계층이 아닌 의존성 방향의 기준으로 횡단을 하게 되는 건가요?
결론
의존성을 안쪽 방향으로 향하도록하고 관심사를 분리 시키는 규칙을 준수해야 한다. 그러면 본질적인 테스트를 하기 쉬운 시스템을 만들게 될 것이다. 또 데이터베이스나 외부 요소의 변경이 있더라도 교체로 인한 영향 없이 교체할 수 있다.