phantasmicmeans 기술 블로그

[Clean Architecture] 14. 컴포넌트 결합 본문

Programming/Clean Architecture

[Clean Architecture] 14. 컴포넌트 결합

phantasmicmeans 2021. 12. 30. 03:03
  • ADP: 의존성 비순환 원칙
  • 하향식(top-down) 설계
  • SDP & SAP

ADP: 의존성 비순환 원칙

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

 

숙취 증후군

 

  • 동일한 소스 파일을 수정하는 환경에서 발생. 누군가가 마지막으로 수정한 코드 때문에 정상 동작하지 않음

주 단위 빌드(Weekly build)

 

  • 한 주의 첫 4일은 알아서 코딩하고 마지막 날 몰아서 통합
  • 결국 통합 이슈를 겪게 되고 효율성 저하

순환 의존성 제거하기

 

  • 개발 환경을 릴리즈 가능한 컴포넌트 단위로 분리하는 것
  • 개발자가 해당 컴포넌트가 동작하도록 만든 후, 해당 컴포넌트를 릴리스하여 다른 개발자가 사용할 수 있도록 함
  • 해당 컴포넌트를 사용하는 개발자들은 릴리즈 된 버전을 사용, 새 릴리즈를 사용은 각 팀에서 알아서 판단

라이브러리를 생각하면 됨. 이 절차가 성공적으로 동작하려면 컴포넌트 의존성 구조에 순환이 있어서는 안됨.

 

방향 그래프이고, 의존성 관계는 방향이 있는 간선에 해당한다. 위 컴포넌트 의존성 구조의 경우 어떤 컴포넌트에서 시작하더라도 cycle을 생성하지 않는다.

 

즉, 비순환 방향 그래프(Directed Acyclic Graph)

 

  • Presenters 로 부터 영향을 받는 컴포넌트는 View, Main 컴포넌트이다.
  • Presenter 담당 팀에서 새 릴리즈를 만들게 되면 이 두 컴포넌트를 작업중인 개발자는 Presenter의 새 릴리즈와 언제 통합할지를 결정해야한다.
  • Presenter 개발자가 이 컴포넌트를 테스트하고자 한다면, 단순히 현재 사용중인 버전의 Interactors, Entities를 이용하기만 하면 된다.
  • 시스템 전체를 릴리즈해야 할 때가 오면 상향식으로 진행한다. (Entities -> Database, Interactors, .. Presenters, View..)

 

순환이 컴포넌트 의존성 그래프에 미치는 영향

새로운 요구사항이 발생해 Entities에 포함된 클래스 하나가 Authorizer에 포함된 클래스 하나를 사용하도록 변경해야한다.

 

  • EntitesUser 클래스에서 AuthorizerPermission 클래스를 사용한다.

아래 그림처럼 순환 의존성(dependency cycle)이 발생한다.

 

순환은 즉각적인 문제를 일으킨다.

 

순환에 의해 Database 컴포넌트는 Entities, Interactors 뿐만 아니라 Authroizer 까지 의존하게 된다. 사실상 거대한 컴포넌트가 되어버림

 

순환 끊기

컴포넌트 사이의 순환을 끊고 의존성을 다시 비순환 방향 그래프(Directed Acyclic Graph) 로 복구해야한다.

 

  1. 의존성 역전 원칙 (DIP)
  • User 가 필요로 하는 메서드를 제공하는 인터페이스를 생성한다. 이 인터페이스는 Entities에 / Authorizer에서는 이 인터페이스를 상속
  • 이렇게 의존성을 역전 시킴으로서 순환을 끊음

 

  1. Entities와 Authorizer가 모두 의존하는 새 컴포넌트 생성

 

흐트러짐 (Jitters)

위의 두번째 해결책에서 보여지듯이 컴포넌트는 요구사항에 따라 변경될 수 있다. 애플리케이션이 성장함에 따라 의존성 구조는 서서히 흐트러진다. 언제나 순환이 발생하는지를 관찰해야한다.

 

하향식 설계

컴포넌트 구조는 하향식으로 설계될 수 없다. 컴포넌트 자체가 시스템에서 가장 먼저 설계할 수 있는 대상이 아니며, 오히려 시스템이 성장하고 변경될 때 함께 진화한다.

 

아무런 클래스도 설계하지 않은 상태에서 컴포넌트 의존성 구조를 설계하려고 하면 실패를 할 것이다.

 

공통 폐쇄 원칙(CCP)에 대해 그다지 파악하고 있지 않고, 재사용 가능한 요소도 알지 못하며, 컴포넌트를 생성할 때 거의 확실히 순환 의존성이 발생할 것이다.

 

컴포넌트 의존성 구조는 시스템의 논리적 설계에 발맞춰 성장하며 또 진화해야 한다.

 

SDP: 안정된 의존성 원칙

안전성의 방향으로(더 안정된 쪽에) 의존하라.

설계는 결코 정적일 수 없다. 설계를 유지하다 보면 변경은 불가피하다. 공통폐쇄원칙(CCP)를 준수함으로써 컴포넌트가 다른 유형의 변경에는 영향받지 않으면서도 특정 유형의 변경에만 민감하게 만들 수 있다.

 

  • 이처럼 컴포넌트 중 일부는 변동성을 지니도록 설계되고 이러한 컴포넌트는 언젠가 변경되리라고 예상한다.
  • 변경이 쉽지 않은 컴포넌트가 변동이 예상되는 컴포넌트에 의존하게 만들어서는 안된다. 한번 의존하게 되면 변동성이 큰 컴포넌트도 결국 변경이 어려워진다.

어느 순간 모듈을 변경하는 일이 상당히 도전적인 일이 되어버리니..

 

안전성 의존 원칙 (Stable Dependencies Principe, SDP)를 준수하면 변경하기 어려운 모듈이 변경하기 쉽게 만들어진 모듈에 의존하지 않도록 만들 수 있다.

 

안전성

소프트웨어 컴포넌트를 변경하기 어렵게 만드는 확실한 방법 하나는 수많은 다른 컴포넌트가 해당 컴포넌트에 의존하게 만드는 것

 

  • 컴포넌트 안쪽으로 들어오는 의존성이 많아지면 상당히 안정적이라고 볼 수 있음 > 사소한 변경이라도 변경에 상당한 노력이 듬

X는 안정된 컴포넌트

 

  • 3개의 컴포넌트가 X에 의존, X가 변경되지 않아야 할 이유가 3가지나 됨
  • 이 경우 X는 세가지 컴포넌트를 책임진다고 함
  • 반대로 X는 어디에도 의존하지 않으므로 독립적이라고 함

Y는 불안정한 컴포넌트

 

  • 어떤 컴포넌트도 Y에 의존하지 않기에 Y는 책임성이 없다.
  • Y는 변경이 발생할 수 있는 외부 요인이 3가지나 된다. 이 경우 Y는 의존적이다.

 

안전성 지표

어떻게 컴포넌트 안전성을 측정하는가

 

  • 컴포넌트로 들어오고 나가는 의존성 개수를 세어보는 방법
  • Fan-in: 안으로 들어오는 의존성. 이 지표는 컴포넌트 내부의 클래스에 의존하는 컴포넌트 외부의 클래스 개수를 나타낸다.
  • Fan-out: 바깥으로 나가는 의존성. 이 지표는 컴포넌트 외부의 클래스에 의존하는 컴포넌트 내부의 클래스 개수를 나타낸다.
  • I(불안정성): I = Fan-out / (Fan-in + Fan-out). 
    • 이 지표는 [0, 1] 범위의 값을 갖는다.
    • I = 0 이면 최고로 안정된 컴포넌트라는 뜻이다.
    • I = 1 이면 최고로 불안정한 컴포넌트라는 뜻이다.

 

Cc의 컴포넌트 안정성

 

  • Fan-in: 3, Cc 내부 클래스에 의존하며 Cc 외부에 있는 클래스
  • Fan-out: 1, Cc 내부 클래스가 의존하며 Cc 외부에 있는 클래스
  • I: 1 / (3 + 1)

I값이 1이면 어떤 컴포넌트도 해당 컴포넌트에 의존하지 않지만(Fan-in = 0), 해당 컴포넌트는 다른 컴포넌트에 의존한다는 뜻(Fan-out > 0)

 

  • 이러한 상태는 컴포넌트가 가질 수 있는 최고 불안정한 상태
  • 자신에게 의존하는 컴포넌트가 없으므로 이 컴포넌트는 변경하지 말아야 할 이유가 없다.
  • 그러나 이 컴포넌트가 다른 컴포넌트에 의존하고 있으니 언젠가는 이 컴포넌트를 변경해야할 이유가 있다.

반대로 I값이 0이면, 해당 컴포넌트에 의존하는 다른 컴포넌트가 있지만(Fan-in > 0), 해당 컴포넌트 자체는 다른 컴포넌트에 의존하지 않는다. (Fan-out = 0)

 

  • 이러한 상태는 컴포넌트가 가질 수 있는 최고로 안정된 상태
  • 자신에게 의존하는 컴포넌트가 있으므로 변경이 어렵지만
  • 해당 컴포넌트를 변경하도록 강제하는 의존성은 없다.

SDP(Stable Dependencies Principe)에서 컴포넌트의 I 지표는 그 컴포넌트가 의존하는 다른 컴포넌트들의 I 보다 커야한다고 말한다.

 

즉, 의존성 방향으로 갈수록 I 지표 값이 감소해야 한다.

 

모든 컴포넌트가 안정적이어야 하는 것은 아니다.

모든 컴포넌트가 최고로 안정적인 시스템이라면 변경이 불가능하다. 이는 바람직한 상황이 아니고 우리가 컴포넌트 구조를 설계할 때 기대하는 것은 불안정한 컴포넌트도 있고 안정된 컴포넌트도 존재하는 상태다.

 

 

위 그림은 세 컴포넌트로 구성된 시스템이 가질 수 있는 이상적인 구조의 다이어그램이다.

 

  • 가장 위쪽이 변경 가능한 컴포넌트, 아래는 안정된 컴포넌트
  • 다이어그램에서 불안정한 컴포넌트를 관례적으로 위쪽에 둔다.(따르면 유용)
  • 위로 향하는 화살표가 있으면 SDP를 위배하는(ADP도 위반하는) 상태가 되기 때문이다.
Comments