‘클린 아키텍처’ 기술 서적에 대해 학습했던 내용을 정리하기 위한 목적의 TIL 포스팅입니다.🙆♂️
- 아키텍처 경계를 완벽하게 만드는데는 비용이 많이 든다.
- 쌍방향(ex. InputBoundary와 OutputBoundary)의 다형적 Boundary 인터페이스, Input 과 Output 을 위한 데이터 구조를 만들어야할 뿐만 아니라, 두 영역을 독립적으로 컴파일하고 배포할 수 있는 컴포넌트로 격리하는데 필요한 모든 의존성을 관리해야 한다.
- 이렇게 만들려면 엄청난 노력을 기울여야 하고, 유지하는데 또 엄청난 노력이 든다.
- 뛰어난 아키텍트라면 이러한 경계를 만드는 비용이 너무 크다 판단하면서도, 한편으론 나중에 필요할 수도 있으므로 이러한 경계에 필요한 공간을 확보하기 원할 수도 있다.
- 애자일 커뮤니티에 속한 많은 사람들은 이러한 종류의 선행적 설계를 탐탁치 않게 여기는데, YAGNI(You Aren’t Going to Need it, ‘필요한 작업만 해라’ 라는 익스트림 프로그래밍의 원칙) 원칙을 위반하기 때문이다.
- 하지만 아키텍트라면 “어쩌면 필요할지도”라는 생각이 들수도 있기에 부분적 경계를 구현해볼 수 있다.
마지막 단계를 건너뛰기
- 부분적 경계를 생성하는 방법 하나는 독립적으로 컴파일하고 배포할 수 있는 컴포넌트를 만들기 위한 작업은 모두 수행한 후, 단일 컴포넌트에 그대로 모아만 두는 것이다.
- 쌍방향 인터페이스, 입출력 데이터 구조를 포함하여 모든 것이 완전히 준비되어 있다.
- 하지만 이모두를 단일 컴포넌트로 컴파일 후 배포한다.
- 이처럼 부분적 경계를 만들려면 완벽한 경계를 만들때 만큼의 코드량과 사전 설계가 필요하지만, 다수의 컴포넌트를 관리하는 작업 및 추적을 위한 버전 번호, 배포 관리 부담은 필요없게 된다. 이 차이는 가볍지 않다.
FitNess 예시
- 부분적 경계 전략을 기반으로 FitNess는 웹 서버 컴포넌트가 위키나 테스트 영역과는 분리되도록 설계했다.
- 새로운 웹 기반 애플리케이션을 만들 때 해당 웹 컴포넌트를 재사용할 수도 있다고 생각했기 때문이다.
- 그러나 시간이 흐르며, 별도로 분리한 웹 컴포넌트가 재사용 될 가능성은 전혀 없을 것임이 명백해졌다.
- 웹 컴포넌트와 위키 컴포넌트 사이의 구분도 약화되기 시작했다..
일차원 경계
- 완벽한 아키텍처 경계는 양방향으로 격리된 상태를 유지해야하므로 쌍방향 Boundary 인터페이스를 사용한다.
- 하지만 이는 초기 설정시나 유지시에 비용이 많이 든다.
- 추후 완벽한 형태의 경계로 확장할 수 있는 공간을 확보하고자 할 때
전략(Strategy) 패턴
활용할 수 있다.
- Client는 Service Boundary를 사용하며 이는 ServiceImpl가 구현한다.
- Client를 ServiceImpl로부터 격리 시키고자 의존성 역전 원칙을 적용하였다.
- 그러나 쌍방향 인터페이스가 없고 개발자와 아키텍트가 제대로 훈련되어 있지 않다면, 전략 패턴은 위에 점섬과 같은 비밀 통로가 생길 수 있다…
퍼사드
- 훨씬 더 간단한 경계로써 모든 서비스 클래스를 메서드 형태로 정의하고 있는 Facade 클래스가 있다.
- 클라이언트는 서비스 클래스를 직접 접근할 수 없다.
- 그러나 정적 언어일 경우 클라이언트가 모든 서비스 클래스에 대해 추이 종속성 가지게된다.
- 이는 서비스 클래스 하나가 변경되면 클라이언트도 무조건 재 컴파일해야한다…
결론
- 아키텍처 경계를 부분적으로 구현하는 간단한 방법 세 가지를 살펴봤는데 이외에도 방법은 많다.
- 각 접근법은 비용과 장점이 다른데, 상황을 고려하여 신중히 선택해야 한다.
- 아키텍처 경계가 언제, 어디에 존재해야 할지, 그리고 그 경계를 완벽하게 구현할지 아니면 부분적으로 구현할지를 결정하는 일 또한 아키텍처의 역할이다.