본문 바로가기
SW core/SW Architecture

컴포넌트 결합 - ADP(의존성 비순환 원칙)

by ocwokocw 2021. 2. 10.

- 이 글은 로버트 C.마틴의 Clean Architecture를 기반으로 작성되었습니다. (가능하면 책을 읽어보는것을 추천한다.)

- 개요

컴포넌트 의존성 그래프에 순환이 있어서는 안 된다.

 

소스를 수정한 후, 테스트를 하고 뿌듯한 마음으로 퇴근을 하였다. 그런데 다음날 회사에 와서 보니 소스가 수정한대로 동작하지 않는다. 이게 뭔일이지 하고 원인을 추적해보니 다른사람이 고친 부분때문에 내 코드가 동작하지 않는다. 작은 프로젝트에서는 이런일이 일어날 가능성이 작고, 일어난다고 해도 금방 고칠 수 있다. 하지만 프로젝트가 크면 문제가 심각해진다.

 

이를 위한 해결책에 두 가지 방법이 있다. 첫번째는 주 단위 빌드이며, 두번째는 의존성 비순환 원칙(ADP)이다.


- 주 단위 빌드

주 단위 빌드 과정은 다음과 같다. 4일동안 개발자는 소스를 수정한다. 그러다 마지막 금요일이 되면 소스를 통합한다.

 

프로그램 규모가 작은 초기에는 순조롭게 진행된다. 하지만 프로그램은 커지고 점차 소스 통합이 오래 걸리기 시작한다. 상황이 심각해지면 개발자들은 금요일 하루에 소스통합이 불가능해져 목요일부터 수행하기 시작한다. 상황은 점점 악화되고, 빌드 일정은 점점 늘린다.


- 컴포넌트 의존성

이 문제 해결책은 릴리스 가능한 컴포넌트 단위로 분리하는것이다. 컴포넌트는 특정 개발 담당자나, 큰 규모 프로젝트의 경우 개발팀이 관리한다.

 

개발자는 자신의 컴포넌트를 개발한 후 릴리스 한다. 이에 번호를 부여하고, 타 컴포넌트에서 자신의 컴포넌트를 사용할 수 있도록 한다. 타 컴포넌트 담당자는 해당 컴포넌트가 릴리스 될 때, 그것을 곧바로 적용할 지 아니면 추후 적용할 지 판단한다. 이렇게 서로 즉각적인 영향없이 작업이 진행된다.

 

컴포넌트만 분리된다고 문제가 해결되는것은 아니다. 이 전략을 성공적으로 수행하려면 컴포넌트 간의 의존성을 관리해야한다. 아래 다이어그램을 보도록 하자.

위 다이어그램에서 각 컴포넌트를 정점으로 생각하고, 의존성을 간선으로 생각하면 방향 그래프가 된다. 

 

이 간선의 의미는 간선의 출발지가 간선의 목적지 컴포넌트에 영향을 받는다는 얘기가 된다. Interactor 컴포넌트 개발자가 릴리스를 새로 찍으면 Interfactor에 의존하던 Main, Controller, Authorizer, Database 컴포넌트가 모두 영향을 받는다.

 

전체 시스템을 빌드해야 하는 상황이오면 상향식으로 빌드 한다. 위 그래프에서는 Entities 를 먼저 빌드 후, Interactor를 그리고 Database, Authorizer, Controller, Main 으로 빌드한다. 그래프를 탐색하면서 차수를 기록해둔다면, 차수가 높은것에서 낮은순 방향으로 빌드를 하면 되겠다. 


- 순환의 문제점

만약 기능이 변경되어 Entities가 Authorizer를 사용한다면 다이어그램은 아래와 같다. 이 때 Interactor, Entities, Authorizer에 생기는 순환때문에 문제가 발생한다.

Database 컴포넌트 담당자는 자신의 컴포넌트가 Interactor 에 영향을 받는다는 사실을 알고 있다. Interactor는 Entities에, Entities는 Authorizer에, Authorizer는 Interactor에 영향을 받는다. 기껏 영향을 적게 받으려고 컴포넌트로 분리해놓았는데 하나의 거대한 컴포넌트가 되어버렸다.

 

또 앞에서 전체 빌드시 차수가 높은 순에서 낮은 순으로 빌드를 해야 한다고 했는데, 어떤 순서로 빌드를 먼저 해야할지도 상황이 애매해졌다.


- 해결책

인터페이스를 이용하여 DIP(의존성 역전)로 Entities와 Authorizer 컴포넌트의 의존 관계를 역전시킨다. 이 때 인터페이스는 Entities에 이 인터페이스를 상속받는 파일을 Authorizer 컴포넌트에 위치한다.

또 다른 해결책은 아래와 같이 새로운 New Component 를 따로 분리하여 의존 관계에 순환이 생기지 않게 재설정한다.

 

- 컴포넌트 의존관계 설계 시점

흔히 하는 착각중에 하나가 시스템의 전체적인 컴포넌트를 설계 하고, 프로그램을 작성한다는것이다. 컴포넌트 의존성 다이어그램은 기능사이의 상관관계를 표현한것이 아니다. 빌드 가능성 및 유지보수성과 관련이 있다. 유지보수할 프로그램이 없는 프로젝트 초기에 빌드 가능성과 유지보수를 미리 설계하는가?

 

프로젝트가 진행됨에 따라 컴포넌트가 늘어나고 시스템 변경범위를 줄이기 위해 SRP(단일 책임)와 CCP(공통 폐쇄)를 적용한다.

 

여기서 더 진행이 되면 재사용 가능한 요소를 만드는 일에 집중한다. 이 때 CRP(공통 재사용)이 관여하기 시작한다. 이런 컴포넌트 의존관계 설정시점을 관찰하다가 순환 관계가 생기면 ADP를 적용하여 순환을 제거해야 한다.

댓글