짧고 단순한 사례를 통해 뛰어난 아키텍트가 일을 처리하는 과정과 결정을 내리는 모습을 살펴보자.
제품: 비디오 판매 웹 서비스
- 판매하길 원하는 비디오들이 있고, 개인과 기업에게 웹을 통해 판매한다.
- 개인은 단품 가격을 지불해 스트리밍으로 본다.
- 개인은 더 높은 가격을 지불하여 비디오를 다운로드해서 영구 소장할 수 있다.
- 기업용 라이선스는 스트리밍 전용이다.
- 기업용 라이선스로 대량 구매시 할인을 받을 수 있다.
- 개인은 시청자인 동시에 구매자
- 기업은 다른 사람들이 시청할 비디오를 구매하는 사람이 따로 있다.
- 비디오 제작자는 비디오 파일과 설명서, 부속 파일(시험, 문제, 해법, 소스 코드 등)을 제공한다.
- 관리자는 신규 비디오 시리즈물을 추가한다.
- 관리자는 기존 시리즈물에 비디오를 추가 도는 삭제한다.
- 관리자는 다양한 라이선스에 맞춰 가격을 책정한다.
유스케이스 분석
주요 액터는 구매자, 시청자, 제작자, 관리자 네 가지이다.
단일 책임 원칙에 따라 네 액터가 시스템이 변경되어야 할 네 가지 주요 근원이 된다.
신규 기능 추가나, 기존 기능 변경의 이유는 액터 중 하나에게 해당 기능을 제공하기 위함이므로, 시스템을 분할하여 특정 액터를 위한 변경이 나머지 액터에게는 전혀 영향을 미치지 않게 만들어야한다.
중앙 점선으로 된 유스케이스는 추상 유스케이스이다.
추상 유스케이스는 범용적인 정책을 담고 있으며, 다른 유스케이스에서 이를 더 구체화한다.
시청자 입장에서 카탈로그 조회하기와 구매자 입장에서 카탈로그 조회하기 유스케이스는 모두 카탈로그 조회하기라는 추상 유스케이스를 상속받는다.
- 이 추상 유스케이스를 다이어그램에서 없애더라도 전체 제품의 기능을 조금도 손상시키지 않지만, 이들 두 유스케이스는 너무 비슷하기 때문에, 유사성을 식별하여 분석 초기에 통합하는 방법을 찾는 방법이 더 현명하다고 판단하였다.
컴포넌트 아키텍처
액터와 유스케이스를 식별했으므로, 예비 단계의 컴포넌트 아키텍처를 만들어 볼 수 있다.
이중으로 된 선은 아키텍처 경계를 나타낸다.
- 뷰 프레젠터, 인터랙터, 컨트롤러로 분리된 전형적이 분할 방법을 활용했다.
- 대응하는 액터에 다라 카테고리를 분리했다.
특수한 컴포넌트인 Catalog View
와 Catalog Presenter
는 카탈로그 조회하기라는 추상 유스케이스를 처리하는 방식으로 뷰와 프레젠터는 해당 컴포넌트 내부에 추상 클래스로 코드화될 것이며, 상속받는 컴포넌트에서는 이를 추상클래스로부터 상속받은 뷰와 프레젠터 클래스들을 포함한다.
시스템을 이러한 컴포넌트들로 모두 분할한다면, 모든 컴포넌트를 분할해서 여러개의 .jar
등 파일로 전달할 수도 있고 모두 한 파일로도 합칠 수 있다.
이는 선택지를 열어두는 것이며, 선택지를 열어두면, 시스템이 변경되는 양상에 맞춰 시스템 배포 방식을 조정할 수 있다.
의존성 관리
위 그림에서 제어흐름은 오른족에서 왼쪽으로 이동한다.
- 입력이 컨트롤러에서 발생
- 인터렉터에 의해 처리되어 결과가 만들어짐
- 프레젠터가 결과의 포멧을 변경
- 뷰가 화면에 표시
대부분의 화살표가 왼쪽에서 오른쪽으로 향하는데, 이는 아키텍처가 의존성 규칙을 준수하기 때문이다.
모든 의존성은 경계선을 한 방향으로만 즉, 항상 더 높은 수준의 정책을 포함하는 컴포넌트로 향해야한다.
사용 관계(열린 화살표)는 제어흐름과 같은 방향을 가리키며, 상속 관계(닫힌 화살표)는 제어흐름과는 반대 방향을 가르키는데, 이는 개방 폐쇄 원칙을 적용했음을 보여준다.
이를 통해 의존성이 올바른 방향으로 흐르며, 저수준의 세부사항에서 발생한 변경이 상위로 파급되어 상위 수준의 정책에 영향을 미치지는 않음을 보장할 수 있다.
결론
그림으로 확인할 수 있는 단일 책임 원칙에 기반한 액터의 분리와 의존성 규칙 모두 서로 다른 이유로, 서로 다른 속도로 변경되는 컴포넌트를 분리하는 데 그 목적이 있다.
- 서로 다른 이유라는 것은 액터와 관련이 있다.
- 서로 다른 속도라는 것은 정책 수준과 관련이 있다.
이러한 방식으로 코드를 한번 구조화하고 나면 시스템을 실제로 배포하는 방식은 다양하게 선택할 수 있게된다.