클린 아키텍처 (Chapter 12~17) - Robert C. Martin


컴포넌트 원칙

SOLID 원칙이 벽과 방에 벽돌을 배치하는 방법을 알려준다면, 컴포넌트 원칙은 빌딩에 방을 배치하는 방법을 설명해준다.
큰 빌딩과 마찬가지로 대규모 소프트웨어 시스템은 작은 컴포넌트들로 만들어진다.

12. 컴포넌트

컴포넌트는 배포 단위이다. 컴포넌트는 시스템의 구성 요소로 배포할 수 있는 가장 작은 단위다. 자바의 경우 jar파일이 컴포넌트다.

런타임에 플러그인 형태로 결합할 수 있는 동적 링크 파일이 이 책에서 말하는 소프트웨어 컴포넌트에 해당한다.



13. 컴포넌트 응집도

어떤 클래스를 어느 컴포넌트에 포함시켜야 할까? 이는 중요한 결정이므로 제대로 된 소프트웨어 엔지니어링 원칙의 도움을 받아야 한다.
이 장에서는 컴포넌트 응집도와 관련된 세 가지 원칙을 논의한다.

  • REP: 재사용/릴리스 등가 원칙 (Reuse/Release Equivalence Principle)
  • CCP: 공통 폐쇄 원칙 (Common Closure Principle)
  • CRP: 공통 재사용 원칙 (Common Reuse Principle)


- REP: 재사용/릴리스 등가 원칙 (Reuse/Release Equivalence Principle)
재사용 단위는 릴리스 단위와 같다.

이 원칙을 소프트웨어 설계와 이케틱처 관점에서 보면 단일 컴포넌트는 응집성 높은 클래스와 모듈들로 구성되어야 함을 뜻한다.
단순히 뒤죽박죽 임의로 선택된 클래스와 모듈로 구성되어서는 안 된다.
컴포넌트를 구성하는 모든 모듈은 서로 공유하는 중요한 테마나 목적이 있어야 한다.

하나의 컴포넌트로 묶인 클래스와 모듈은 반드시 함께 릴리스할 수 있어야 한다.
하나의 컴포넌트로 묶인 클래스와 모듈은 버전 번호가 같아야 하며, 동일한 릴리스로 추적 관리되고, 동일한 릴리스 문서에 포함되어야 한다는 사실은 컴포넌트 제작자 입장이나 사용자 입장에서도 이치에 맞는 얘기다.

- CCP: 공통 폐쇄 원칙 (Common Closure Principle)
동일한 이유로 동일한 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라. 서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라.

이 원칙은 단일 책임 원칙(SRP)을 컴포넌트 관점에서 다시 쓴 것이다.
SRP에서 단일 클래스는 변경의 이유가 여러 개 있어서는 안 된다고 말하듯이, 공통 폐쇄 원칙(CCP)에서도 마찬가지로 단일 컴포넌트는 변경의 이유가 여러개 있어서는 안 된다고 말한다.

CCP는 같은 이유로 변경될 가능성이 있는 클래스는 모두 한곳으로 묶을 것을 권한다.
물리적 또는 개념적으로 강하게 결합되어 항상 함께 변경되는 클래스들은 하나의 컴포넌트에 속해야 한다.

  • SRP와의 유사성
    CCP는 컴포넌트 수준의 SRP다. SRP에서는 서로 다른 이유로 변경되는 메서드를 서로 다른 클래스로 분리하라고 말한다.
    CCP에서는 서로 다른 이유로 변경되는 클래스를 서로 다른 컴포넌트로 분리하라고 말한다. 두 원칙은 모두 다음과 같은 교훈으로 요약할 수 있다.

동일한 시점에 동일한 이유로 변경되는 것들을 한데 묶어라. 서로 다른 시점에 다른 이유로 변경되는 것들은 서로 분리하라

- CRP: 공통 재사용 원칙 (Common Reuse Principle)
CRP는 어떤 클래스를 한데 묶어도 되는지보다는, 어떤 클래스를 한데 묶어서는 안 되는지에 대해서 훨씬 더 많은 것을 이야기한다.
CRP는 강하게 결합되지 않은 클래스들을 동일한 컴포넌트에 위치시켜서는 안 된다고 말한다.

필요하지 않은 것에 의존하지 말라.

결론
어느 클래스들을 묶어서 컴포넌트로 만들지를 결정할 때, 재사용성과 개발 가능성이라는 상충하는 힘을 반드시 고려해야 한다.
이들 사이에서 애플리케이션의 요구에 맞게 균형을 잡는 일은 중요하다. 심지어 이 균형점은 거의 항상 유동적이다.
결과적으로 시간이 흐름에 따라 프로젝트의 초점이 개발가능성에서 재사용성으로 바뀌고, 그에 따라 컴포넌트를 구성하는 방식도 조금씩 흐트러지고 또 진화한다.



14. 컴포넌트 결합

지금부터 다룰 세 가지 원칙은 컴포넌트 사이의 관계를 설명한다. 이 장에서도 마찬가지로 개발 가능성과 논리적 설계 사이의 균형을 다룬다.
컴포넌트 구조와 관련된 아키텍처를 침범하는 힘은 기술적이며, 정치적이고, 가변적이다.

- ADP: 의존성 비순환 원칙 (Acyclic Dependencies Principle)
컴포넌트 의존성 그래프에 순환(cycle)이 있어서는 안 된다.

하루 종일 일해서 무언가를 작동하게 만들어 놓고 퇴근했는데, 이튿날 출근해 보면 전혀 돌아가지 안흔 경험을 해본 적이 있지 않은가?
왜 작동하지 않게 되었나? 왜냐하면 누군가 당신보다 더 늦게까지 일하면서 당신이 의존하고 있던 무언가를 수정했기 때문이다.
나는 이러한 현상을 ‘숙취 증후군 (the morning after syndrome)’이라고 부른다.

‘숙취 증후군 (the morning after syndrome)’은 많은 개발자가 동일한 소스 파일을 수정하는 환경에서 발생한다.
지난 수십 년 동안 이 문제의 해결책으로 두 가지 방법이 발전되어 왔는데, 이 두 해결책은 모두 통신 업계에서 만들어졌다.
첫 해결책은 ‘주 단위 빌드(weekly build)’이며, 두 번째 해결책은 ‘의존성 비순환 원칙(Acyclic Dependencies Principle, ADP’이다.

  • 주 단위 빌드 (Weekly Build)
    주 단위 빌드는 중간 규모의 프로젝트에서는 흔하게 사용된다. 격주 빌드는 잠깐 동안은 만족스럽겠지만, 프로젝트 규모가 성장하면서 통합에 드는 시간은 계속해서 늘어간다.
    이 같은 흐름은 마침내 위기를 초래한다.

  • 순환 의존성 제거
    이 문제의 해결책은 개발 환경을 릴리스 가능한 컴포넌트 단위로 분리하는 것이다. 이를 통해 컴포넌트는 개별 개발자 또는 단일 개발팀이 책임질 수 있는 작업 단위가 된다.

개발자가 해당 컴포넌트가 동작하도록 만든 후, 해당 컴포넌트를 릴리스하여 다른 개발자가 사용할 수 있도록 만든다.
담당 개발자는 이 컴포넌트에 릴리스 번호를 부여하고, 다른 팀에서 사용할 수 있는 디렉터리로 이동시킨다. 그런 다음 개발자는 자신만의 공간에서 해당 컴포넌트를 지속적으로 수정한다.
나머지 개발자는 릴리스된 버전을 사용한다.

컴포넌트가 새로 릴리스되어 사용할 수 있게 되면, 다른 팀에서는 새 릴리스를 당장 적용할지를 결정해야 한다. 적용하지 않기로 했다면 그냥 과거 버전의 릴리스를 계속 사용한다.
새 릴리스를 적용할 준비가 되었다는 판단이 들면 새 릴리스를 사용하기 시작한다.

이 같은 작업 절차는 단순하며 합리적이어서 널리 사용되는 방식이다. 하지만 이 절차가 성공적으로 동작하려면 컴포넌트 사이의 의존성 구조를 반드시 관리해야 한다.
의존성 구조에 순환이 있어서는 안 된다. 의존성 구조에 순환이 생기면 ‘The morning after syndrome’을 피해 갈 수 없다.

clean_archit016
컴포넌트 다이어그램에서는 컴포넌트를 조립하여 애플리케이션을 만드는 다소 전형적인 구조를 볼 수 있다.

이 구조가 방향 그래프(directed graph)임에 주의하자. 컴포넌트는 정점(vertex)에 해당하고, 의존성 관계는 방향이 있는 간선(directed edge)에 해당한다.
한 가지 더 주목할 점이 있다. 어느 컴포넌트에서 시작하더라도, 의존성 관계를 따라가면서 최초의 컴포넌트로 되돌아갈 수 없다는 사실이다. 이 구조에는 순환이 없다.
즉, 이 구조는 비순환 방향 그래프(Directed Acyclic Graph, DAG)다.

Presenters 컴포넌트를 만드는 개발자가 이 컴포넌트를 테스트하고자 한다면, 단순히 현재 사용 중인 버전의 Interactors와 Entities를 이용해서 Presenters 자체 버전을 빌드하면 그만이다. 이 빌드 과정에 시스템의 나머지 컴포넌트는 전혀 관련이 없다. 멋진 일이다. 즉, Presenters를 만드는 개발자가 테스트를 구성할 때 대체로 적은 노력이 든다는 뜻이며, 고려해야 할 변수도 상적으로 적다는 뜻이기도 하다.


clean_archit017
새로운 요구상이 발생해서 Entities에 포함된 클래스 하나가 Authorizer에 포함된 클래스 하나를 사용하도록 변경할 수밖에 없다고 가정해 보자.
예를 들어 Entities의 User 클래스가 Authorizer의 Permissions 클래스를 사용한다고 해보자. 이렇게 되면 그림에서 보듯이 순환 의존성(dependency cycle)이 발생한다.

이 순환은 즉각적인 문제를 일으킨다. 예를 들면, Database 컴포넌트를 만드는 개발자는 컴포넌트를 릴리스하려면 Entities 컴포넌트와 반드시 호환되어야 한다는 사실을 알고 있다.
하지만 Entities 컴포넌트에는 순환이 있으므로, Database 컴포넌트는 또한 Authorizer와도 호환되어야 한다. 그런데 Authorizer는 Interactors에 의존한다.
이로 인해 Database는 릴리스하기가 훨씬 어려워진다. Entities, Authorizer, Interactors는 사실상 하나의 거대한 컴포넌트가 되어 버린다.

Entities 컴포넌트를 테스트할 때 무슨 일이 벌어질지를 생각해 보라. 유감스럽게도 Authorizer와 Interactors까지도 반드시 빌드하고 통합해야 한다.

이처럼 순환이 생기면 컴포넌트를 분리하기가 상당히 어려워진다. 단위 테스트를 하고 릴리스를 하는 일도 굉장히 어려워지며 에러도 쉽게 발생한다.
게다가 모듈의 개수가 많아짐에 따라 빌드 관련 이슈는 기하급수적으로 증가한다.

순환 끊기
컴포넌트 사이의 순환을 끊고 의존성을 다시 DAG로 원상복구하는 일은 언제라도 가능하다. 이를 위한 주요 메커니즘 두 가지를 살펴보자.

clean_archit018

  • 의존성 역전 원칙(DIP)을 적용한다.
    그림 처럼 User가 필요로 하는 메서드를 젝오하는 인터페이스를 생성한다.


clean_archit019

  • Entities와 Authorizer가 모두 의존하는 새로운 컴포넌트를 만든다.

컴포넌트 의존성 다이어그램은 애플리케이션의 기능을 기술하는 일과는 거의 관련이 없다.
오히려 컴포넌트 의존성 다이어그램은 애플리케이션의 빌드 가능성(build ability)과 유지보수성(maintain ability)을 보여주는 지도와 같다.
바로 이러한 이유 때문에 컴포넌트 구조는 프로젝트 초기에 설계할 수 없다.

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

- SDP: 안정된 의존성 원칙 (Stable Dependencies Principle, SDP)
안정성의 방향으로 (더 안정된 쪽에) 의존하라.

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

clean_archit021
그림의 X는 안정된 컴포넌트. 세 컴포넌트가 X에 의존하며, 따라서 X 컴폰넌트는 변경하지 말아야 할 이유가 세 가지나 되기 때문이다.
이 경우 X는 세 컴포넌트를 책임진다(responsible)라고 말한다.
반대로 X는 어디에도 의존하지 않으므로 X가 변경되도록 만들 수 있는 외적인 영향이 전혀 없다.
이 경우 X는 독립적이다(independent)라고 말한다.


clean_archit022
그림의 Y는 상당히 불안정한 컴포넌트다. 어떤 컴포넌트도 Y에 의존하지 않으므로 Y는 책임성이 없다고 말할 수 있다.
또한 Y는 세 개의 컴포넌트에 의존하므로 변경이 발생할 수 있는 외부 요인이 세 가지다. 이 경우 Y는 의존적이라고 말한다.


I(불안정성): I = Fan-out / (Fan-in + Fan-out).
I=0이면 최고로 안정된 컴포넌트라는 뜻이다. I=1이면 최고로 불안정한 컴포넌트라는 뜻이다.

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

- SAP: 안정된 추상화 원칙 (Stable Abstractions Principle, SAP)
컴포넌트는 안정된 정도만큼만 추상화되어야 한다.

A(추상화 정도): A=Na(컴포넌트의 추상 클래스와 인터페이스의 개수)/Nc(컴포넌트의 클래스 개수) A가 0이면 컴포넌트에는 추상 클래스가 하나도 없다는 뜻이다. A가 1이면 컴포넌트는 오로지 추상 클래스만을 포함한다는 뜻이다.


clean_archit024

고통의 구역(Zone of pain)
(0,0) 주변 구역에 위치한 컴포넌트를 살펴보자. 이 컴포넌트는 매우 안정적이며 구체적이다. 이러한 컴포넌트는 바람직한 상태가 아닌데, 뻣뻣한 상태이기 때문이다.
추상적이지 않으므로 확장할 수 없고, 안정적이므로 변경하기도 상당히 어렵다. 따라서 제대로 설계된 컴포넌트라면 (0,0) 근처에는 위치하지 않을 거라고 보는 게 일반적이다.
(0,0) 주변 영역은 배제해야 할 구역이며, Zone of pain이라고 부른다.
변동성이 없는 컴포넌트는 (0,0) 구역에 위치했더라도 해롭지 않다. 변동 될 가능성이 거의 없기 때문이다.
이러한 이유로 고통의 구역에서 문제가 되는 경우는 변동성이 있는 소프트웨어 컴포넌트다.

쓸모없는 구역(Zone of Uselessness)
(1,1) 주변의 컴포넌트를 생각해 보자. 이 영역도 바람직하지 않은데, 여기 위치한 컴포넌트는 최고로 추상적이지만, 누구도 그 컴포넌트에 의존하지 않기 때문이다.
이러한 컴포넌트는 쓸모가 없다. 따라서 이 영역은 쓸모없는 구역(Zone of uselessness)이라고 부른다.

배제 구역 벗어나기
각 배제 구역으로부터 최대한 멀리 떨어진 점의 궤적은 (1,0)과 (0,1)을 잇는 선분이다. 나는 이 선분을 주계열(Main Sequence)이라고 부른다.
주계열에 위치한 컴포넌트는 자신의 안정성에 비해 ‘너무 추상적’이지도 않고, 추상화 정도에 비해 ‘너무 불안정’하지도 않다.
이들 컴포넌트는 주계열바로 위에 또는 가깝게 위치할 때 가장 이상적이다.



아키텍처

15. 아키텍처란?

소프트웨어 아키텍트는 최고의 프로그래머이며, 앞으로도 계속 프로그래밍 작업을 맡을 뿐만 아니라 동시에 나머지 팀원들이 생산성을 극대화 할 수 있는 설계를 하도록 방향을 이끌어 준다.

소프트웨어 시스템의 아키텍처란 시스템을 구축했던 사람들이 만들어낸 시스템의 형태다.
그 모양은 시스템을 컴포넌트로 분할하는 방법, 분할된 컴포넌트를 배치하는 방법, 컴포넌트가 서로 의사소통하는 방식에 따라 정해진다.
그리고 그 형태는 아키텍처 안에 담긴 소프트웨어 시스템이 쉽게 개발, 배포, 운영, 유지보수되도록 만들어진다.

좋은 아키텍처는 시스템을 쉽게 이해하고, 쉽게 개발하며, 쉽게 유지보수하고, 또 쉽게 배포하게 해준다.
아키텍처의 궁극적인 목표는 시스템의 수명과 관련된 비용은 최소화하고, 프로그래머의 생산성은 최대화하는 데 있다.

선택사항 열어 두기
소프트웨어를 부드럽게 유지하는 방법은 선택사항을 가능한 한 많이, 그리고 가능한 한 오랫동안 열어 두는 것이다. 열어 둬야 할 선택사항이란 무엇일까?
그것은 바로 중요치 않은 세부사항(detail)이다.

모든 소프트웨어 시스템은 주요한 두 가지 구성요소로 분해할 수 있다. 바로 정책(policy)과 세부사항이다.
정책 요소는 모든 업무 규칙과 업무 절차를 구체화한다. 정책이란 시스템의 진정한 가치가 살아 있는 곳이다.

세부사항은 사람, 외부 시스템, 프로그래머가 정책과 소통할 때 필요한 요소지만, 정책이 가진 행위에는 조금도 영향을 미치지 않는다.
이러한 세부사항에는 입출력 장치, 데이터베이스, 웹 시스템, 서버, 프레임워크, 통신 프로토콜 등이 있다.

아키텍트의 목표는 시스템에서 정책을 가장 핵심적인 요소로 식별하고, 동시에 세부사항은 정책에 무관하게 만들 수 있는 형태의 시스템을 구축하는 데 있다.
이를 통해 세부사항을 결정하는 일은 미루거나 연기할 수 있게 된다.

뛰어난 아키텍트라면 이러한 결정이 아직 내려지지 않은 것처럼 행동하며, 여전히 결정을 가능한 한 오랫동안 연기하거나 변경할 수 있는 형태로 시스템을 만든다.
좋은 아키텍트는 결정되지 않은 사항의 수를 최대화한다.

결론
좋은 아키텍트는 세부사항을 정책으로부터 신중하게 가려내고, 정책이 세부사항과 결합되지 않도록 엄격하게 분리한다.
이를 통해 정책은 세부사항에 관한 어떠한 지식도 갖지 못하게 되며, 어떤 경우에도 세부사항에 의존하지 않게 된다.
좋은 아키텍트는 세부사항에 대한 결정을 가능한 한 오랫동안 미룰 수 있는 방향으로 정책을 설계한다.



16. 독립성

좋은 아키텍처는 다음을 지원해야 한다.

  • 시스템의 유스케이스
  • 시스템의 운영
  • 시스템의 개발
  • 시스템의 배포

유스케이스
첫 번째 주요 항목인 유스케이스의 경우, 시스템의 아키텍처는 시스템의 의도를 지원해야 한다는 뜻이다.
좋은 아키텍처가 행위를 지원하기 위해 할 수 있는 일 중에서 가장 중요한 사항은 행위를 명확히 하고 외부로 드러내며, 이를 통해 시스템이 지닌 의도를 아키텍처 수준에서 알아볼 수 있게 만드는 것이다.

운영
시스템이 초당 100,000명의 고객을 처리해야 한다면, 이케틱처는 이 요구와 관련된 각 유스케이스에 걸맞은 처리량과 응답시간을 보장해야 한다.
만약 시스템에서 수 밀리초 안에 3차원의 빅데이터 테이블에 질의해야 한다면, 반드시 이러한 운영 작업을 허용할 수 있는 형태로 아키텍처를 구조화해야 한다.

이상하게 보일 수도 있지만, 이러현 걸정은 뛰어난 아키텍트라면 열어 두어야 하는 선택사항 중의 하나다.
아키텍처에서 각 컴포넌트를 적절히 격리하여 유지하고 컴포넌트 간 통신 방식을 특정 형태로 제한하지 않는다면, 시간이 지나 운영에 필요한 요구샇ㅇ이 바뀌더라도 스레드, 프로세스, 서비스로 구성된 기술 스펙트럼 사이를 전환하는 일이 훨씬 쉬워질 것이다.

개발
아키텍처는 개발환경을 지원하는 데 있어 핵심적인 역할을 수행한다. 콘웨이(conway)의 법칙이 작용하는 지점이 바로 여기다.
콘웨이의 법칙은 다음과 같다.

시스템을 설계하는 조직이라면 어디든지 그 조직의 의사소통 구조와 동일한 구조의 설계를 만들어 낼 것이다.

배포
아키텍처는 배포 용이성을 결정하는 데 중요한 역할을 한다. 이때 목표는 ‘즉각적인 배포(immediate deployment)’다.

  • 좋은 아키텍처는 수십 개의 작은 설정 스크립트나 속성 파일을 약간씩 수정하는 방식을 사용하지 않는다.
  • 좋은 아키텍처는 꼭 필요한 디렉터리나 파일을 수작업으로 생성하게 내버려 두지 않는다.
  • 좋은 아키텍처라면 시스템이 빌드된 후 즉각 배포할 수 있도록 지원해야 한다.



17. 경계: 선 긋기

소프트웨어 아키텍처는 선을 긋는 기술이며, 나는 이러한 선을 경계(boundary)라고 부른다.
경계는 소프트웨어 요소를 서로 분리하고, 경계 한편에 잇는 요소가 반대편에 있는 요소를 알지 못하도록 막는다.

clean_archit025
경계선은 상속 관계를 횡단하면서 Database Interface 바로 아래에 그어진다.
이 도표에서 DatabaseAccess가 존재한다는 사실을 알고 있는 클래스는 없다는 뜻이다.

clean_archit026
화살표의 방향에 주목하자. Database는 BusinessRules에 대해 알고 있다. BusinessRules는 Database에 관해 알지 못한다.
이는 DatabaseInterface 클래스는 BusinessRules 컴포넌트에 속하며, DatabaseAccess 클래스는 Database 컴포넌트에 속한다는 사실을 의미한다.

두 컴포넌트 사이에 이러한 경계선을 그리고 화살표의 방향이 BusinessRules를 향하도록 만들었으므로, BusinessRules에서는 어떤 종류의 데이터베이스도 사용할 수 있음을 알 수 있다.
데이터베이스는 오라클, MySQL, 카우치, Atomic 등으로 구현할 수 있고, 심지어 플랫 파일로도 구현할 수 있다. 업무 규칙은 전혀 개의치 않는다.
그리고 이 같은 사실은 데이터베이스에 대한 결정은 연기할 수 있으며, 데이터베이스를 결정하기에 앞서 업무 규칙을 먼저 작성하고 테스트하는 데 집중할 수 있음을 의미한다.

입력과 출력은?
GUI를 보고선 GUI가 시스템이라고 생각하곤 한다. 이들은 시스템을 GUI 측면에서 정의하므로, 처음부터 GUI가 동작하는 모습을 반드시 볼 수 있어야 한다고 믿는다.
이들은 매우 중요한 원칙을 깨닫지 못했다. 입력과 출력은 중요하지 않다는 사실이다.
이 원칙은 처음에는 이해하기 힘들다. 우리는 시스템의 행위를 입출력이 지닌 행위적 측면에서 생각하는 경향이 있다.

비디오 게임을 생각해 보자.
이 경우 사용자 경험은 인터페이스에 의해 좌우된다. 화면, 마우스, 버튼, 음향이 바로 그 인터페이스다. 이러한 인터페이스 뒤에는 인터페이스를 조작하는 모델이 존재한다는 사실을 잊어버린다.
더 중요한 사실은 모델은 인터페이스를 전혀 필요로 하지 않는다는 점이다. 게임이 화면에 전혀 출력되지 않더라도 모델은 게임에서 발생되는 모든 이벤트를 모델링하면서 주어진 역할을 충실하게 수행한다.
인터페이스는 모델에게 있어 중요하지 않다. 중요한 것은 업무 규칙이다.

플러그인 아키텍처
사실 소프트웨어 개발 기술의 역사는 플러그인을 손쉽게 생성하여, 확장 가능하며 유지보수가 쉬운 시스템 아키텍처를 확립할 수 있게 만드는 방법에 대한 이야기다.

clean_archit027

교체작업은 사소한 일은 아닐 것이다.
그렇다 하더라도 플러그인 구조를 가정한 채 시작함으로써, 최소한 우리는 이러한 변경 작업을 현실성 있도록 만들었다.

결론
소프트웨어 아키텍처에서 경계선을 그리려면 먼저 시스템을 컴포넌트 단위로 분할해야 한다. 일부 컴포넌트는 핵심 업무 규칙에 해당한다.
나머지 컴포넌트는 플러그인으로, 핵심 업무와는 직접적인 관련이 없지만 필수 기능을 포함한다.
그런 다음 컴포넌트 사이의 화살표가 특정 방향, 즉 핵심 업무를 향하도록 이들 컴포넌트의 소스를 배치한다.
의존성 화살표는 저수준 세부사항에서 고수준의 추상화를 향하도록 배치된다.





Reference

  • 클린 아키텍처 (로버트 C. 마틴)

Tag: [ book  clean-architecture  component  ]