hexdrinker

경계 해부학

-2 min read

시스템 아키텍처는 컴포넌트와 그 컴포넌트들을 분리하는 경계에 의해 정의된다. 경계는 다양한 형태로 나타난다.

경계 횡단하기

'런타임에 경계를 횡단한다'는 것은 경계 한쪽에서 반대편 기능을 호출하여 데이터를 전달하는 일이다. 경계 횡단은 소스 코드 의존성 관리에서 온다.

모듈 하나가 변경되면 이에 의존하는 다른 모듈도 변경이나 재컴파일이 필요할지 모른다. 경계는 이러한 변경이 전파되는 것을 막는 방화벽을 만들고 관리하는 수단으로써 존재한다.

두려운 단일체

경계 중 가장 단순하며 가장 흔한 형태는 물리적으로 엄격하게 구분되지 않는 형태다. 이 형태에서는 함수와 데이터가 단일 프로세서에서 같은 주소 공간을 공유하며 나름의 규칙에 따라 분리되어 있을 뿐이다. 이는 소스 수준의 분리 모드에 해당한다.

배포 관점에서 본다면 단일 실행 파일이므로 경계가 드러나지 않는다. 하지만 경계가 실제로 존재하지 않거나 의미 없는 것은 아니다.

이러한 아키텍처는 대부분 동적 다형성에 의존하여 내부 의존성을 관리한다. 가장 단순한 형태의 경계 횡단은 저수준 클라이언트에서 고수준 서비스로 향하는 함수 호출이다.

배포형 컴포넌트

아키텍처의 경계가 물리적으로 드러날 수도 있는데 그중 가장 단순한 형태는 동적 링크 라이브러리다. .NET DLL, jar 파일, 루비 젬(Gem), 유닉스 공유 라이브러리 등이 그 예시다.

컴포넌트를 이런 형태로 배포하면 따로 컴파일하지 않고 바로 쓸 수 있다. 대신 컴포넌트는 바이너리와 같이 배포 가능한 형태로 전달된다. 이는 배포 수준의 결합 분리 모드에 해당한다.

단일체와 마찬가지로 배포형 컴포넌트의 경계 간 통신은 함수 호출이므로 매우 값싸다.

스레드

단일체와 배포형 컴포넌트 모두 스레드를 쓸 수 있다. 스레드는 경계도 아니고 배포 단위도 아니며 실행 계획과 순서를 체계화 하는 방법에 가깝다.

모든 스레드가 단 하나의 컴포넌트에 포함될 수도 있고 많은 컴포넌트에 걸쳐 분산될 수도 있다.

로컬 프로세스

훨씬 강한 물리적 형태를 띄는 경계로는 로컬 프로세스가 있다. 로컬 프로세스들은 동일한 프로세서 또는 하나의 멀티코어 시스템에 속한 여러 프로세서들에서 실행되지만, 각각이 독립된 주소 공간에서 실행된다.

종종 공유 메모리 파티션을 사용하기도 하지만, 일반적으로 메모리 보호를 통해 프로세스들이 메모리 공유를 못하게 한다.

대개 소켓(socket)이나 메일 박스(mailbox), 메시지 큐(message queue)와 같이 OS에서 제공하는 통신 기능을 활용한다.

서비스

물리적인 형태를 띠는 가장 강력한 경계는 바로 서비스다. 서비스는 프로세스로, 자신의 물리적 위치에 구애받지 않는다. 서로 통신하는 두 서비스는 물리적으로 동일한 프로세서나 멀티코어에서 동작할 수도 있고, 아닐 수도 있다.

서비스로 경계를 지나는 통신은 함수 호출에 비해 느린 편이다. 따라서 빈번하게 통신하는 일을 최대한 피해야 한다.

결론

단일체를 제외한 대부분의 시스템은 한 가지 이상의 경계 전략을 사용한다. 즉, 대체로 한 시스템 안에서도 통신이 빈번한 로컬 경계와 지연을 중요하게 고려해야 하는 경계가 혼합되어 있음을 의미한다.