clean-architecture

18. 경계 해부학

시스템 아키텍처는 일련의 소프트웨어 컴포넌트와 그 컴포넌트들을 분리하는 경계에 의해 정의된다.

이러한 경계는 다양한 형태로 나타난다.

경계 횡단하기


적절한 위치에서 경계를 횡단하게 하는 비결은 소스 코드 의존성 관리에 있다.

소스 코드 모듈 하나가 변경되면, 이에 의존하는 다른 소스 코드 모듈도 변경하거나, 다시 컴파일해서 새로 배포해야 할지도 모르기 때문이다. 경계는 이러한 변경이 전파되는 것을 막는 방화벽을 구축하고 관리하는 수단으로써 존재한다.

두려운 단일체


소스 수준 분리 모드 - 물리적으로 엄격하게 구분되지 않는 형태

배포 관점에서 볼 때 단일체는 경계가 드러나지 않는다. 그렇다고 해서 단일체에는 경계가 실제로 존재하지 않거나, 경계 자체가 무의미하다는 뜻은 아니다.

객체 지향이 없었다면, 또는 다형성에 해당하는 메커니즘이 없었다면, 아키텍트는 결합도를 적절히 분리하기 위해 함수를 가리키는 포인터라는 위험한 옛 관행에 기대야만 했을 것이다.

단일체에서 컴포넌트 간 통신은 매우 빠르고 값싸다. 통신은 전형적인 함수 호출에 지나지 않기 때문이다.

배포형 컴포넌트


동적 링크 라이브러리 : 아키텍쳐의 경계가 물리적으로 드러나는 가장 단순한 형태

컴포넌트를 이 형태로 배포하면 따로 컴파일하지 않고 곧바로 사용할 수 있다.

스레드


스레드는 아키텍처 경계도 아니며 배포 단위도 아니다. 이보다 스레드는 실행 계획과 순서를 체계화하는 방법에 가깝다.

로컬 프로세스


로컬 프로세스들은 동일한 프로세서 또는 하나의 멀ㄹ티코어 시스템에 속한 여러 프로세서들에서 실행되지만, 각각이 독립된 주소 공간에서 실행된다. 종종 공유 메모리 파티션을 사용하기도 하지만, 일반적으로는 메모리 보호를 통해 프로세스들이 메모리를 공유하지 못하게 한다.

로컬 프로세스 예시

정적으로 링크된 단일체이거나 동적으로 링크된 여러개의 컴포넌트로 구성될 수 있다.

로컬 프로세스는 컴포넌트 간 의존성을 동적 다형성을 통해 관리하는 저수준 컴포넌트로 구성된다.

소스 코드 의존성의 화살표는 항상 고수준 컴포넌트를 향한다.

서비스


물리적인 형태를 띠는 가장 강력한 경계는 바로 서비스다.

서비스는 자신의 물리적 위치에 구애받지 않는다.

서비스 경계를 지나는 통신은 함수 호출에 비해 매우 느리다. 전체 소요 시간이 수십 밀리초에서 수 초까지 걸릴 수 있다. 따라서 주의를 기울여서 가능하다면 빈번하게 통신하는 일을 피해야 한다.

지연에 따른 문제를 고수준에서 처리할 수 있어야 한다.

저수준 서비스는 반드시 고수준 서비스에 플러그인 되어야 한다.

결론


대다수의 시스템은 한 가지 이상의 경계 전략을 사용한다.

서비스 경계를 활용하는 시스템이라면 로컬 프로세스 경계도 일부 포함하고 있을 수 있다. 실제로 서비스는 상호 작용하는 일련의 로컬 프로세스 퍼사드에 불과할 때가 많다.

또한 개별 서비스 또는 로컬 프로세스는 거의 언제나 소스 코드 컴포넌트로 구성된 단일체이거나, 혹은 동적으로 링크된 배포형 컴포넌트의 집합이다.

대체로 한 시스템 안에서도 통신이 빈번한 로컬 경계와 지연을 중요하게 고려해야 하는 경계가 혼합되어 있음을 의미한다.