본문 바로가기
Engineering/SW Architecture

클린 아키텍쳐 (7) - 사례 연구 : 비디오 판매

by 쿨쥰 2023. 4. 4.

이전 글 : 세부사항

2023.03.31 - [Engineering/SW Architecture] - 클린 아키텍쳐 (6) - 세부사항

 

클린 아키텍쳐 (6) - 세부사항

이전 글 : 아키텍처 [부분적 경계, 계층과 경계, 메인 컴포넌트, 크고작은 모든 서비스들, 테스트 경계] 2023.03.26 - [Engineering/SW Architecture] - 클린 아키텍쳐 (5) - 아키텍처 [부분적 경계, 계층과 경계,

skidrow6122.tistory.com

 

 


 

 

 

지금까지 살펴본 아키텍처에 대한 규칙과 견해를 종합해서 사례 연구로 적용해 본다.

제품

사례 연구를 위해 선정한 제품은 웹 사이트에서 비디오를 판매하는 SW이다.

판매되는 비디오들이 있고, 그것을 개인과 기업에게 웹을 통해 판매한다.

개인은 단품 가격을 지불하여 스트리밍으로 볼 수도 있고, 더 높은 가격을내고 비디오를 다운로드 해서 영구 소장할 수도 있다.

기업용 라이선스는 스트리밍 전용이며, 대량 구매를 하면 할인 받을 수 있다.

일반적으로 개인은 시청자인 동시에 구매자다. 반면에 기업은 다른 사람들이 시청할 비디오를 구매하는 총무팀 따위가 따로 있다.

비디오 제작자는 비디오 파일과 비디오에 대한 설명서, 부속 파일을 제공한다. 부속 파일에는 시험, 문제, 해법, 소스 코드 등이 포함된다.

관리자는 신규 비디오 시리즈물을 추가하거나 기존 시리즈물에 비디오를 추가 또는 삭제하며, 다양한 라이선스에 맞춰 가격을 책정한다.

자, 이제 이 시스템의 초기 아키텍처를 결정하는 첫 단계는 액터와 유스케이스를 식별하는 일이다.

 

유스케이스 분석

사례 연구를 위해 선정한 제품은 웹 사이트에서 비디오를 판매하는 SW이다.

판매되는 비디오들이 있고, 그것을 개인과 기업에게 웹을 통해 판매한다.

전형적인 유스케이스 분석

네 개의 주요 액터는 분명하다.

단일 책임 원칙 SRP 에 따르면 이들 네 액터가 시스템이 변경되어야 할 네가지 주요 근원이 된다.

따라서 액터에 따라 시스템을 분할하여, 특정 액터를 위한 변경이 나머지 액터에게는 전혀 영향을 미치지 않게 만들어야 한다.

상기 다이어그램의 유스케이스 목록은 완벽하지는 않다.

예를 들면, 로그인이나 로그아웃 관련 유스케이스는 찾을 수가 없는데, 이는 하나의 시스템에 대한 모든 유스케이스를 포함하기에는 내용이 너무 방대해져서 간소화 시킨 예제라서 그렇다.

중앙의 점선으로 된 두개의 유스케이스를 주목하자.

이들은 추상 유스케이스이다.

추상 유스케이스는 범용적인 정책을 담고 있으며, 다른 유스케이스에서 이를 더 구체화 한다.

시청자 입장에서 카탈로그 조회하기와 구매자 입장에서의 카탈로그 조회하기 유스케이스는 모두 카탈로그 조회하기라는 추상 유스케이스를 상속받는다.

물론, 이 추상화를 꼭 생성해야만 제품의 기능을 모두 구현할 수 있는 것이 아니기 때문에 필수는 아니다.

하지만 이들 두 유스케이스는 너무도 비슷하므로, 유사성을 식별하여 분석 초기에서 부터 통합하는 방법을 찾는 것이 더 현명하다고 판단한 결과이다.

 

컴포넌트 아키텍처

이제 액터와 유스케이스를 식별했으므로, 예비 단계의 컴포넌트 아키텍처를 만들어 볼 수 있다.

예비단계의 컴포넌트 아키텍처

다이어그램에서 이중으로 된 선은 아키텍처 경계를 나타낸다.

이 경계를 횡단하는 뷰, 프레젠터, 인터랙터, 컨트롤러로 분리된 전형적인 분할 방법을 확인 할 수 있다.

또한 대응하는 액터에 따라 카테고리를 분리했다는 사실도 확인 할 수 도 있다.

여기서 각 컴포넌트는 단일 .jar 파일 또는 .dll 파일에 해당한다.

이들 컴포넌트 각각은 자신에게 할당된 뷰, 프레젠터, 인터랙터, 컨트롤러를 포함한다.

특수한 컴포넌트인 Catalog View와 Catalog Presenter 에 주목해 보자.

이는 카탈로그 조회하기 라는 추상 유스케이스를 처리하는 방식에 해당한다.

이 뷰와 프레젠터는 해당 컴포넌트 내부에 추상 클래스로 코드화 될 것이며, 상속받는 컴포넌트에서는 이들 추상 클래스로부터 상속받은 뷰와 프레젠터 클래스들을 포함한다.

사실 정말로 시스템을 이러한 컴포넌트들로 모두 분리해서 여러개의 .jar로 만들 수도 있고 아닐 수도 있다.

하지만 정석대로라면 컴파일과 빌드 환경은 분명하게 이 형태로 나눠야 하며, 따라서 각 컴포넌트를 독립적으로 전달 할 수 있게 빌드하는 것도 가능할 것이다.

여기에 추가로 전달해야할 이 모든 단위를 더 적은 개수로 합칠 수 도 있다. 예를 들어 뷰, 프레젠터, 인터랙터, 컨트롤러, 유틸리티 각각을 합쳐 총 다섯개의 .jar 파일로 쉽게 합칠 수 도 있는 것이다. 그러면 서로 독립적으로 변경 될 가능성이 큰 컴포넌트들을 독립적으로 배포할 수 있게 된다.

뷰와 프레젠터를 합쳐서 같은 .jar에 두고, 인터랙터/컨트롤러/유틸리티는 그대로 개별 .jar 파일에 두는 방식도 있다.

더 원시적으로 두개의 .jar파일을 생성해서 하나에 뷰/프레젠터를, 다른 하나에 나머지 모두를 포함시키는 방식으로 합칠 수도 있다.

이처럼 선택지를 열어두면 후에 시스템이 변경되는 양상에 맞추어 시스템 배포방식을 조정할 수 있게 된다.

 

의존성 관리

위 다이어그램에서의 제어흐름은 오른쪽에서 왼쪽으로 이동한다. 

입력이 컨트롤러에서 발생하면 인터랙터에 의해 처리되어 결과가 만들어진다.

그런 후 프레젠터가 결과의 포맷을 변경하고 뷰가 화면에 표시하는 것이다.

여기서 모든 화살표가 오른쪽에서 왼쪽을 가리키지 않음을 주목하자.

사실 대다수의 화살표는 왼쪽에서 오른쪽으로 향한다. 이는 아키텍처가 의존성 규칙을 준수하기 때문이다.

모든 의존성은 경계선을 한 방향으로만 가로지르는데, 항상 더 높은 수준의 정책을 포함하는 컴포넌트로 향한다.

또 하나, 사용 관계(열린 화살표)는 제어흐름과 같은 방향을 가리키며, 상속 관계(닫힌 화살표)는 제어흐름과는 반대 방향을 가리킴에 주목하자.

이는 개발 폐쇄 원칙 OCP 를 준수했음을 보여준다.

이를 통해 우리는 의존성이 올바른 방향으로 흐르며, 따라서 저수준의 세부사항에서 발생한 변경이 상위로 파급되어 상위 수준의 정책에 영향을 미치지 않음을 보장 할 수 있다.

 

결론

위 아키텍처 다이어그램은 두 가지 서로 다른 차원의 분리 개념을 포함하고 있다.

하나는 단일 책임 원칙에 기반한 액터의 분리이며, 두 번째는 의존성 규칙이다.

이 두 차원은 모두 서로 다른 이유로, 서로 다른 속도로 변경되는 컴포넌트를 분리하는 데 그 목적이 있다.

서로 다른 이유라는 것은 액터와 관련이 있으며, 서로 다른 변경의 속도라는 것은 정책 수준과 관련이 있다.

이런 방식으로 코드를 한번 구조화하고 나면 시스템을 실제로 배포하는 방식은 다양하게 선택할 수 있게 된다.

상황에 맞게 컴포넌트들을 배포가능한 단위로 묶을 수도 있고, 상황이 변하면 변한 상황에 맞추어 묶는 단위를 바꾸기도 쉬워진다.

 

댓글