컴포넌트 응집성, 영어로 풀어보자면 Component Conhesion이다. 여기에 컴포넌트 응집도와 관련된 세 가지 원칙을 이야기 한다.
- REP(Reuse/Release Equivalence Principle) : 재사용/릴리스 등가 원칙
- CCP(Common Closure Principle) : 공통 폐쇄 원칙
- CRP(Common Reuse Principle) : 공통 재사용 원칙
REP - 재사용/릴리스 등가 원칙
저자는 모듈 관리 도구의 중요해짐을 설파한다. 사실 파이썬에서도 비슷하다. 이러한 모듈 관리 - 혹은 패키지 관리 도구들은 소프트웨어의 재사용을 어떻게 하면 잘 할지를 도와준다. 각각의 언어에 대해 사용하는 소프트웨어 모듈, 패키지 혹은 버전 관리 도구들은 다음과 같다.
- Java - maven, gradle
- Ruby - RVM, rbenv
- Closure - Leiningen
- Python - pip, pyenv, poetry
- JavaScript - yarn, npm, NVM
사실 이러한 모듈 매니저, 버전 매니저 들은 추적을 위한 기능이다. 즉, 프로그램을 버전 - 숫자 혹은 다양한 알파벳 - 으로 관리하여 절차를 만드는 것이다. 물론 이 절차에 대해 다양한 의견들이 있고 다양한 정책들이 있다. 내가 생각하기에 이러한 절차, 넘버링이 대표적으로 등장하는 곳이 깃허브이며 그에 대한 정책이 나타나는 것이 gitflow 전략이라고 본다.
깃 플로우 전략이 현재 개발자에게 가장 잘 보여줄 수 있는 재사용/릴리스 등가 원칙이 아닐까 생각한다. 각각의 feautre, develop, release, hot fixes, 그리고 master(혹은 main)을 간략히 설명하면 다음과 같다.
- master(혹은 main): 제품 출시 버전 관리를 위한 브랜치
- develop: 다음 출시 버전을 위한 개발 전용 브랜치
- feature: 새로운 기능의 개발을 위한 브랜치
- release: 다음 출시를 준비하늩 브랜치
- hotfix: 이미 출시한 제품의 버그를 고치기 위한 브랜치
사실 다양한 버전이 있지만, 나는 이 모두가 결국 이 책에서 제시하는 컴포넌트 응집도를 높이고 이에 대한 재사용과 릴리스를 더 좋게 하가 위해 사용하는 것이 아닐까해서 나온 전략이 아닐까 생각한다. - 물론 이 깃 플로우 전략은 웹 어플리케이션에는 어울리지 않는 다고 한다, 주된 소프트웨어 버전 관리가 필요한 iOS나 Android 어플리케이션 혹은 퍼블릭 패키지 같이 공개되어 있는 것에 어울린다고 한다.
아무튼 이러한 gitflow 전략은 결국 번호 혹은 알파벳 같은 것을 부여하여 추적을 용이하게 하고, 릴리스에 태그를 달아 컴포넌트들이 서로 호환되는지 보증하기 위한 전략이라고 생각한다.
이러한 REP에 대하여 저자는 "컴포넌트를 구성하는 모든 모듈은 서로 공유하는 중요한 테마나 목적이 있어야 한다"의 필요성을 제기한다. 하지만, 이러한 문구는 굉장히 애매하다. 저자는 너무 당연하다는 듯이 이야기 하지만, 실제 제품을 출시할 때 과연 어디까지를 같은 테마나 목적으로 보고 선을 그을 것인가는 굉장히 현실세계에서도 애매하기 때문이다.
사실 이러한 문제를 저자도 알고 있어서 굉장히 약점이 큰 원칙으로 이야기 하기도 한다. 내가 보기에는 굉장히 애매한 "공통 테마란?"이라는 질문에 쉽게 대답할 수 없어서 그런 것 같기도 하다. 이를 회사로 예로 들면, "테마나 목적으로 묶인 구성원"인 팀으로도 볼 수 있다. 하지만 이 구성원들이 지닌 생각은 전부 다르며 생각 - 프로그램에서는 릴리스 버전 - 을 Sync하기도 굉장히 어렵다.
이 REP에 대하여 저자가 하고 싶은 말은 CCP와 CRP를 통해 보완을 해서 해결하려고 한다.
CCP- 공통 폐쇄 원칙
동일한 이유로 동일한 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라.
서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라.
처음에 이 부분을 읽을 때 SRP와 굉장히 비슷하다 생각했는데, 역시나 SRP를 컴포넌트 관점에서 다시 쓴 것이라고 저자가 친절하게 설명해 주었다. 사실 이 부분을 읽으면서 든 생각은 - 백엔드 개발자로서 - MSA(Mciro Service Architecture)가 굉장히 좋아할만한 원칙이라는 것이다.
MSA가 도입 혹은 탄생한 이유는 많겠지만 모놀로식의 한계 극복에서 나온 것이라고 생각한다. 결국 모놀리식 애플리케이션의 경우 시간이 경과하면서 코드 종속성이 얽히는 경우가 많기에 MSA는 코드나 데이터 저장소를 공유 - 즉 의존성을 최소하 하면서 - 하지 않으므로 종속성을 최소화한다.
CCP는 동일한 유형의 변경에 대해 닫혀 있는 클래스 - 혹은 기능 - 들을 하나의 컴포넌트로 묶는다. 그리고 이러한 CCP의 원칙으로 묶인 프로그램을 다시금 기능별로 합쳐서 각각의 서비스로 개별화 시킨다. 하지만 MSA같이 CCP를 통해 개별적으로 묶어서 "관리"한다는 것은 개발팀의 규모가 어느정도 있어야 유지될 수 있지 않을까 생각한다.
극 개개의 서비스, 컴포넌트들은 아주 단순하게 관리할 수 있지만, 이 서비스, 컴포넌트들이 서로 영향을 주고 받는 전체 시스템 구조 상으로는 개인으로 관리하기에는 너무 복잡해지는 것이다. 사실 개발팀이 크다고 해도 각 서비스, 컴포넌트들에 대한 관리를 위해 커뮤니케이션이 아주 활발하게 이루어지는 이상적인 상황이 일어나야 한다.
즉, 컴포넌트를 동일한 이유로 묶었다고 해도, 그 컴포넌트가 여러개 이면 오히려 관리의 어려움이 더 늘어나지 않을까 한다.
CRP- 공통 재사용 원칙
컴포넌트 사용자들을 필요하지 않는 것에 의존하게 강요하지 마라.
나는 이 CRP가 컴포넌트 자체에 집중한다고 생각한다. 즉 SOLID원칙에서 나온 ISP처럼, 필요없는 것은 과감하게 쳐내라 - 다른 말로 하자면, 필요 없는 것을 잘 파악해야 한다 - 라는 것처럼 들렸다.
결론
결국 각각의 삼원칙은 상호보완적이지만, 무조건 다 선택할 수 있는 것이 아니라고 느껴졌다. 결국 자신의 상황에 맞춰서 어느 곳의 꼭지점이 약한 지를 먼저 파악하는 것이 중요하다고 생각한다. 만약 REP와 CRP를 우리 팀은 잘 한다고 해보자 이는 곧 너무 많은 컴포넌트의 수정이 이루어지지만, 각각의 모듈, 컴포넌트 혹은 클래스의 재 사용성이 높으며 릴리스 및 배포 주기도 적절하다는 것이다.
클린 아키텍처를 읽으면서 드는 생각은 결국, 팀 혹은 회사에서 프로그램 혹은 코드가 이루어지는 개발 문화가 어떻게 이루어져 있는지 - 혹은 어떻게 이루어질 수 있는지 - 를 제시하고 이에 대한 판단 근거 혹은 기준을 제안해준 다는 점일 것 같다. 물론 이 문화다, 저 문화다를 딱 잘라서 말할 수 없다.
결국 코드도 프로그램도, 제작자 사용자 모두 인간이기에 모호하기 때문이다.