[Clean Architecture 정리] 18장. 경계 해부학
18장. 경계 해부학
시스템 아키텍처는 컴포넌트를 분리하는 경계에 의해서 정의되며 경계는 다양한 형태로 존재한다.
경계 횡단하기
소스 코드의 변경은 의존하는 다른 소스 코드에 영향을 주기 때문에 적절히 경계를 횡단하는 방법은 이러한 소스 코드의 의존성을 관리하는 것이다. 경계는 소스 코드의 변경에 의한 영향을 막는 수단으로써 존재한다.
두려운 단일체
다양한 경계 중 가장 단순하고 흔한 형태는 물리적으로 구분되지 않는 단일 실행 파일 형태의 단일체(monolith)이다.
배포 관점에서 단일체의 경계는 드러나지 않지만, *동적 다형성에 의존해 내부 의존성 관리할 수 있다.
정적 다형성(Static Polymorphism)과 동적 다형성(Dynamic Polymorphism)
정적 다형성(Static Polymorphism)
- Static Binding, 컴파일 시점 바인딩(at Compile), Early Binding, Method Overloading
- 컴파일 시점에 일어나는 바인딩
- 제네릭(Generics)이나 템플릿(Template)을 이용해 타입에 대한 의존성 관리하거나 메서드 오버로딩을 이용해 함수에 대한 의존성을 관리하며, 컴파일러는 컴파일하는 시점에 데이터 타입 또는 함수에 대한 심볼을 해석한다.
동적 다형성(Dynamic Polymorphism)
- Dynamic Binding, 런타임 시점 바인딩(at Runtime), Late Binding, Method Overriding
- 런타임 시점에 일어나는 바인딩(Late Binding)
- 타입을 상위 클래스로 선언하고 팩토리 메서드 패턴 등을 통해 인스턴스를 생성하게 되면 컴파일러는 컴파일 시점에는 데이터 타입에 대해 해석하지 못하고 런타임 시점에 해석할 수 있다.
위의 예시처럼 제어의 흐름은 고수준 클라이언트에서 저수준 서비스로 향하지만 동적 다형성을 이용하면 의존성을 역전시킬 수 있다.
이로인해 컴파일 시점의 의존 방향과 런타임 시점의 의존 방향은 반대가 된다.
또한, 서비스 구현 클래스 사이를 횡단하는 경계를 그어 고수준 컴포넌트와 저수준 컴포넌트를 구분하게 되면, 단일 실행 파일의 모노티릭 구조에서도 구조를 분리할 수 있다.
배포형 컴포넌트
아키텍처의 경계가 물리적으로 드러나는 방법으로 가장 단순한 형태는 동적 링크 라이브러리(DLL, Dynamic Link Library)이다. 컴포넌트는 배포 가능한 형태로 전달되며 배포 수준 결합 분리모드에 해당한다.
모든 함수가 동일한 프로세서와 주소 공간에 위치하며 컴포넌트 분리, 의존성 관리는 단일체 구조와 같은 전략을 사용한다.
함수 호출을 통해 컴포넌트 간 통신이 이루어지기 때문에 통신에 드는 비용이 낮다.
스레드
단일체와 배포형 컴포넌트는 스레드를 활용할 수 있으며 스레드는 아키텍처 경계 보다는 실행 계획, 순서를 체계화하는 방법에 가깝다.
로컬 프로세스
강한 물리적 형태를 띠는 아키텍처 경계로 명령문 또는 시스템 콜에 의해 생성된다.
로컬 프로세스는 독립적인 주소 공간에서 실행되고 프로세스 간 통신은 소켓, 메일박스, 메시지 큐를 이용한다.
각 로컬 프로세스는 정적으로 링크된 단일체이거나 동적으로 링크된 컴포넌트의 조합일 수 있다.
로컬 프로세스 간 분리 전략은 저수준 프로세스가 고수준 프로세스를 의존하게 만들고 저수준 프로세스가 플러그인 될 수 있도록 만드는 것이다.
로컬 프로세스 경계를 지나는 통신은 운영체제 호출, *데이터 마샬링 및 언마샬링, 프로세스 간 문맥 교환 등 비용이 많이 들기 때문에 잦은 통신은 지양해야 한다.
마샬링(Marshalling)과 직렬화(Serialization)
데이터 마샬링은 메모리 상에 형상화된 객체를 다른 데이터 형태로 변환하는 과정을 의미하며, 프로레스 간 데이터 전달을 할 때 사용된다.
직렬화는 데이터 마샬링의 한 과정이며 마샬링이 직렬화를 포함하는 개념이다.
객체 전송 순서
1. 직렬화된 객체를 바이트 단위로 분해(marshalling)
2. 분해된 데이터를 순서대로 전송
3. 전송받은 데이터 복구(unmarshalling)
서비스
물리적인 형태로 가장 강력한 형태를 띠는 경계로 서비스 자체는 프로세스이며 시스템 콜에 의해 동작한다. 서비스 간 통신은 네트워크를 통해 이루어진다고 가정하고 많은 비용이 들기 때문에 잦은 통신은 지양해야 한다.
마찬가지로 저수준 서비스가 고수준 서비스를 의존하게 만들고 저수준 서비스가 플러그인 될 수 있도록 만들어야 한다.
서적 : http://www.yes24.com/Product/Goods/77283734