컴포넌트란컴포넌트 응집도REP(재사용/릴리스 등가 원칙)CCP(공통 폐쇄 원칙)CRP(공통 재사용 원칙)결합도 원칙들의 균형 다이어그램컴포넌트 결합ADP: 의존성 비순환 원칙순환 끊기SDP (안정된 의존성 원칙)안정성SAP (안정된 추상화 원칙)고수준 정책을 어디에 위치시켜야 하는가?추상화 정도 측정하기 & 주계열
컴포넌트란
- 컴포넌트는 배포 단위다.
- 컴포넌트는 시스템의 구성 요소로 배포할 수 있는 가장 작은 단위다.
- 자바의 경우 jar 파일이 컴포넌트
- 루비에서는 gem 파일
- 닷넷에서는 dll
- 컴파일형 언어에서는 바이너리 파일의 결합체
- 인터프리터형 언어의 경우는 소스 파일의 결합체
- 여러 컴포넌트를 서로 링크하여 실행 가능한 단일 파일로 생성할 수 있다.
런타임에 플러그인 형태로 결합할 수 있는 동적 파일이 이 책에서 말하는 소프트웨어 컴포넌트 (컴포넌트 플러그인 아키텍처)
컴포넌트 응집도
어떤 클래스를 어느 컴포넌트에 포함시켜야 할지 결정할 때 도움 얻을 수 있는 원칙 3가지
REP(재사용/릴리스 등가 원칙)
Reuse/Release Equivalence Principle
재사용 단위는 릴리스 단위와 같다
- 하나의 컴포넌트로 묶인 클래스와 모듈은 반드시 함께 릴리스할 수 있어야 한다.
- 하나의 컴포넌트로 묶인 클래스와 모듈은 버전 번호가 같아야 하며, 동일한 릴리스로 추적 관리되고, 동일한 릴리스 문서에 포함되어야 함
- 이 원칙 만으로는 클래스와 모듈을 단일 컴포넌트로 묶는 방법을 제대로 설명하기 힘들고, CCP와 CRP가 제약을 가해줌
CCP(공통 폐쇄 원칙)
Common Closure Principle
동일한 이유로 동일한 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라. 서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라.(CCP는 컴포넌트 수준의 SRP이다)
- 대다수의 애플리케이션에서 유지보수성은 재사용성보다 훨씬 중요하다. 애플리케이션에서 코드가 반드시 변경되어야 한다면, 이러한 변경이 여러 컴포넌트 도처에 분산되어 발생하기 보다는, 차라리 변경 모두가 단일 컴포넌트에서 발생하는 편이 낫다.
- 변경을 단일 컴포넌트로 제한할 수 있다면 해당 컴포넌트만 재배포하면 되고 다른 컴포넌트는 다시 검증하거나 배포할 필요가 없음
- CCP에서는 동일한 유형의 변경에 대해 닫혀 있는 클래스들을 하나의 컴포넌트로 묶음으로써 OCP에서 얻은 교훈을 확대 적용함
CRP(공통 재사용 원칙)
Common Reuse Principle
컴포넌트 사용자들을 필요하지 않는 것에 의존하게 강요하지 말라 (즉, 사용하지 않는 클래스를 가진 컴포넌트에 의존하지 말라. ISP의 포괄적인 버전임)
- 같이 재사용되는 경향이 있는 클래스와 모듈들을 같은 컴포넌트에 포함해야 한다.
- 개별 클래스가 단독으로 재사용되는 경우는 거의 없다.
- 대체로 재사용 가능한 클래스는 재사용 모듈의 일부로써 해당 모듈의 다른 클래스와 상호작용 하는 경우가 많음. CRP에서는 이런 클래스들이 동일한 컴포넌트에 있어야 한다고 말함
- 사용하는 컴포넌트가 사용되는 컴포넌트에서 단 하나의 클래스만 사용한다 하더라도 의존성은 여전함
- 또한, 의존하는 컴포넌트가 있다면 해당 컴포넌트의 모든 클래스에 대해 의존함을 확실하게 인지해야 함. 그 중 일부 클래스에만 의존하고 다른 클래스와는 독립적일 수 없음을 확실히 인지해야 함
- CRP는 어떤 클래스를 한 데 묶어도 되는지 보다는 어떤 클래스를 한데 묶어서는 안 되는지에 대해서 훨씬 더 많은 것을 이야기함
- CRP는 강하게 결합되지 않은 클래스들을 동일한 컴포넌트에 위치시켜서는 안 된다고 말함
- 한 컴포넌트가 다른 컴포넌트에 의존한다면 모든 클래스에 대해 의존하게 되는거니, 해당 컴포넌트 안에 강하게 결합되지 않은 클래스들을 위치시키면 사용하지 않는 클래스를 가진 컴포넌트에 의존하게 되는것! ⇒ 그러니 강하게 결합되지 않은 클래스들 동일한 컴포넌트에 위치 x
결합도 원칙들의 균형 다이어그램

- REP와 CCP는 포함 원칙이고 CRP는 배제 원칙이라 세 원칙은 서로 상충된다.
- 다이어그램의 각 변은 반대쪽 꼭지점에 있는 원칙을 포기했을 때 감수해야 할 비용을 나타냄
- REP와 CCP에만 과도하게 집중하면 불필요한 릴리스가 너무 빈번함.
- 시간이 흐르면서 개발팀이 주의를 기울이는 부분이 변함!
- 예를 들어 프로젝트 초기에는 CCP가 REP보다 훨씬 중요한데 개발 가능성이 재사용성보다 더욱 중요하기 때문
- 일반적으로 프로젝트는 삼각형의 오른쪽에서 시작하는 편이며, 이때는 오직 재사용성만 희생하면 됨
- 프로젝트가 성숙하고, 그 프로젝트로부터 파생된 또 다른 프로젝트가 시작되면, 프로젝트는 점차 삼각형에서 왼쪽으로 이동해 간다.
- 즉, 프로젝트의 컴포넌트 구조는 시간과 성숙도에 따라 변함
어느 클래스들을 묶어서 컴포넌트를 만들지를 결정할 때, 재사용성과 개발가능성이라는 상충하는 힘을 반드시 고려해야 한다. 이들 사이에서 애플리케이션의 요구에 맞게 균형을 잡는 일이 중요하다.
컴포넌트 결합
ADP: 의존성 비순환 원칙
컴포넌트 의존성 그래프에 순환이 있어서는 안된다
- 개발환경을 릴리스 가능한 컴포넌트 단위로 분리하고, 각 컴포넌트 사이의 배포 의존성을 끊음. 다른 컴포넌트에서 릴리스를 하더라도, 해당 컴포넌트의 새로운 릴리스를 적용하는건 각 팀의 자율에 맡길 수 있음
- 이러한 작업절차가 성공적으로 동작하려면 컴포넌트 사이의 의존성 구조를 반드시 관리해야 함
- DAG(Directed Acyclic Graph) 형태로 컴포넌트 의존성 관계를 만들면 릴리스에 영향받는 팀도 쉽게 찾을 수 있을 뿐더러 컴포넌트 테스트를 구성하는 데에도 대체로 적은 노력이 든다.
- 만약 순환이 생기게 되면 하나의 컴포넌트를 테스트하고자 할 때 다른 컴포넌트들과의 호환을 맞추어야 하는데 맞춰야 되는 컴포넌트들의 수도 늘어날 뿐더러 해당하는 순환이 생긴 컴포넌트들이 사실 상 하나의 거대한 컴포넌트가 되어버림(⇒ 컴포넌트 사이에 결합이 발생하게 됨)
- 또한 컴포넌트를 어떤 순서대로 빌드해야 올바른지 파악하는 것도 힘들어진다.
순환 끊기
- DIP 의존성역전 원칙 활용하기
- 두 컴포넌트가 의존하는 새로운 컴포넌트를 만들고 두 컴포넌트에서 모두 의존하는 클래스들을 새로운 컴포넌트로 이동시키기
- 컴포넌트 의존성 다이어그램은 애플리케이션의 기능을 기술하는 일과는 거의 관련이 없다. 오히려 컴포넌트 의존성 다이어그램은 애플리케이션의 빌드 가능성과 유지보수성을 보여주는 지도와 같다.
- 그래서, 컴포넌트 구조는 프로젝트 초기에 설계할 수가 없다(빌드하거나 유지보수할 소프트웨어가 없기때문에)
SDP (안정된 의존성 원칙)
안정성의 방향으로(더 안정된 쪽에) 의존하라
- 변경이 쉽지 않은 컴포넌트가 변동이 예상되는 컴포넌트에 의존하게 만들어서는 절대 안 된다. 한번 의존하게 되면 변동성이 큰 컴포넌트도 결국 변경이 어려워진다.
안정성
- 안정성은 변경을 만들기 위해 필요한 작업량과 관련된다.
- 소프트웨어 컴포넌트를 변경하기 어렵게 만드는 데 많은 요인이 존재하며, 그 예로는 컴포넌트의 크기, 복잡도, 간결함 등을 들 수 있음
- 그러나 여기서는 이러한 요인들은 무시하고, 좀 더 특이한 요인에 집중할 것인데 이는 수많은 다른 컴포넌트가 해당 컴포넌트에 의존하게 만드는 것이다.
- 3개의 컴포넌트가 현재 컴포넌트(X)에 의존하고 현재 컴포넌트가 어느 컴포넌트에도 의존하지 않을 때, X는 3개의 컴포넌트를 책임(responsible)진다고 하고 어디에도 의존하지 않으므로 변경되도록 만들 수 있는 외적인 영향이 전혀 없기에 independent하다고 말한다.
SAP (안정된 추상화 원칙)
컴포넌트는 안정된 정도만큼만 추상화되어야 한다.
고수준 정책을 어디에 위치시켜야 하는가?
- 시스템에서 고수준 정책을 캡슐화하는 소프트웨어는 반드시 안정된 컴포넌트(I=0)에 위치해야 한다.
- 하지만 고수준 정책을 안정된 컴포넌트에 위치시키면 그 정책을 포함하는 소스 코드는 수정하기가 어려워진다. 이로 인해 시스템 전체 아키텍처가 유연성을 잃는다. 컴포넌트가 최대로 안정된 상태이면서(I=0) 동시에 변경에 충분히 대응할 수 있을 정도로 유연하게 만들 수 있을까? ⇒ 개방 폐쇄 원칙에서 찾을 수 있음
- 안정적인 컴포넌트라면 반드시 인터페이스와 추상 클래스로 구성되어 쉽게 확장할 수 있어야 한다.
- 안정된 컴포넌트가 확장이 가능해지면 유연성을 얻게 되고 아키텍처를 과도하게 제약하지 않게 된다.
추상화 정도 측정하기 & 주계열
- 안정성과 추상화 정도 사이의 관계를 정의하고 그래프를 그리기