소개
클린아키텍처: 소프트웨어 구조와 설계의 원칙 책을 읽고 정리하며 소감을 적는 포스트입니다.
부분적 경계
아키텍처 경계를 완벽하게 만드는 데는 비용이 많이 든다. 엄청난 노력을 기울여야 하고, 유지하는 데도 또 엄청난 노력이 든다.
많은 경우에, 뛰어난 아키텍트라면 이러한 경계를 만드는게 비용이 너무 많이 든다고 판단하면서도, 나중에 필요할 수도 있으니 경계에 필요한 공간을 확보하기 원할 수 있다.
애자일 커뮤니티에 속한 사람 중 많은 이가 이러한 종류의 선행적인 설계를 탐탁지 않게 여기는데, YAGNI(You Aren’t Going to Need It) 원칙을 위반하기 때문이다.
하지만 아키텍트라면 이 문제를 검토하면서 “그래, 하지만 어쩌면 필요할지도.”라는 생각이 든다면 부분적 경계(partial boundary)
를 구현해 볼 수 있다.
마지막 단계를 건너뛰기
부분적 경계를 생성하는 방법 하나는 독립적으로 컴파일하고 배포할 수 있는 컴포넌트를 만들기 위한 작업은 모두 수행한 후, 단일 컴포넌트에 그대로 모아만 두는 것이다.
아무리 보아도 이처럼 부분적 경계를 만들려면 완벽한 경계를 만들 때만큼 코드량과 사전 설계가 필요하다. 하지만 다수의 컴포넌트 관리하는 작업은 하지 않아도 된다.
하지만 시간이 흐르면서, 별도로 분리한 컴포넌트가 재사용 될 가능성이 낮아지고 의존성이 잘못된 방향으로 선을 넘기 시작하면 다시 분리하는 작업은 따문한 일이 될 것이다.
일차원 경계
완벽한 형태의 아키텍처 경계는 양방향으로 격리된 상태를 유지해야 하므로 쌍방향 Boundary 인터페이스를 사용한다. 양방향으로 격리된 상태를 유지하려면 초기 설정할 때나 지속적으로 유지할 때도 비용이 많이 든다.
아래의 그림은 전통적인 전략(Strategy)패턴을 사용하여 추후 완벽한 형태로 경계를 확장하기 위해 공간을 확보할 때 사용 된다.
전략(Strategy) 패턴
Client를 ServiceImpl로 부터 격리시키는 데 필요한 의존성 역전을 적용하여 미래에 필요한 아키텍처 경계를 만든다.
하지만 점선 화살표에서 보듯이 이러한 분리는 빠르게 붕괴 될 수 있는데, 쌍방향 인터페이스가 없고 개발자와 아키텍트가 근면 성실하고 제대로 훈련되어 있지 않다면, 이 점선과 같은 비밀 통로가 생기는 일을 막을 수 없다.
퍼사드
훨씬 더 단순한 경계는 퍼사드(Facade) 패턴이다. 아래의 그림과 같으며 의존성 역전까지도 희생한다.
퍼사드(Facade) 패턴
Facade 클래스에는 모든 서비스 클래스를 메서드 형태로 정의하고, 서비스 호출이 발생하면 해당 서비스 클래스로 호출을 전달한다. 클라이언트는 이들 서비스 클래스에 직접 접근 할 수 없다.
하지만 Client가 이 모든 서비스 클래스에 대해 추이 종속성을 가지게 된다. 정적 언어였다면 서비스 클래스 중 하나에서 소스 코드가 변경되면 Client도 무조건 재컴파일 해야 한다.
결론
아키텍처 경계를 부분적으로 구현하는 간단한 방법 세 가지를 살펴봤다.
접근법 각각은 나름의 비용과 장점을 지닌다. 각 접근법은 완벽한 형태의 경계를 담기 위한 공간으로써, 적절하게 사용할 수 있는 상황이 서로 다르다. 또한 각 접근법은 해당 경계가 실제로 구체화되지 않으면 가치가 떨어질 수 있다.
아키텍처 경계가 언제, 어디에 존재해야 할지, 그리고 그 경계를 완벽하게 구현할지 아니면 부분저그올 구현할지를 결정하는 일 또한 아키텍트의 역할이다.