개요
소프트웨어 아키텍처를 설계할 때 흔히 저지르는 오해 중 하나는 코드를 나누는 경계와 실행 단위를 나누는 경계가 하나의 동일한 선이라고 가정하는 것이다. 그러나 이 둘은 본질적으로 다른 층위의 결정이다. 논리적 경계는 개념, 책임, 데이터 소유권을 기준으로 시스템을 나누는 선이며, 물리적 경계는 그 코드가 어떤 프로세스, 어떤 서버, 어떤 데이터베이스, 어떤 네트워크 구간에 배치되는지를 기준으로 시스템을 나누는 선이다. 마이크로소프트의 닷넷 마이크로서비스 아키텍처 가이드는 이를 명시적으로 정의하면서, 논리적 아키텍처와 물리적 아키텍처가 일대일로 대응할 수도 있지만 그렇지 않은 경우가 더 많다고 설명한다.
이 구분이 중요한 이유는, 두 경계를 혼동하는 순간 아키텍처 설계에서 반복적으로 나타나는 여러 실패 패턴, 이를테면 분산 모놀리스, 과도하게 파편화된 마이크로서비스, 겉보기에는 모듈화되었지만 실제로는 모든 것이 서로 얽혀 있는 모놀리스 같은 문제가 발생하기 때문이다. 필립 크루흐텐이 1995년 제안한 4+1 뷰 모델에서 논리 뷰와 물리 뷰를 별도의 관점으로 분리한 것도, 마크 리처즈와 닐 포드가 컴포넌트를 논리적 컴포넌트와 그 물리적 패키징으로 구분해 설명하는 것도, 도메인 주도 설계에서 바운디드 컨텍스트를 서비스나 컨테이너와 동일시하지 말라고 강조하는 것도 모두 같은 문제의식에서 출발한다.
이 문서는 논리적 경계와 물리적 경계를 각각 정의하고, 두 경계가 왜 자연스럽게 어긋나는지, 아키텍처 스타일에 따라 두 경계가 어떻게 배치되는지, 경계를 잘못 다뤘을 때 어떤 문제가 발생하는지, 그리고 이를 실무에서 어떻게 설계해야 하는지를 정리한다.
논리적 경계
정의와 성립 근거
논리적 경계는 시스템을 구성하는 개념, 책임, 규칙, 데이터의 의미를 기준으로 그어지는 경계다. 이 경계는 코드가 어떤 파일에 있는지, 어떤 프로세스에서 실행되는지와 무관하게 존재할 수 있다. 논리적 경계가 답하는 질문은 다음과 같다.
- 이 개념은 누가 소유하는가
- 이 규칙은 어디에서 정의되어야 하는가
- 이 용어는 어떤 맥락에서 어떤 의미를 갖는가
- 어떤 변경이 함께 일어나야 하고, 어떤 변경은 서로 독립적이어야 하는가
CodeOpinion을 운영하는 데릭 코마틴은 논리적 경계를 소유권의 문제로 설명한다. 그는 모듈이나 서비스의 경계를 나눌 때 데이터베이스 테이블이나 배포 단위가 아니라 누가 어떤 개념의 행동, 규칙, 생명주기, 의미에 대한 권한을 갖는지를 기준으로 삼아야 한다고 강조한다. 예를 들어 인사 모듈에서 직원의 근무 상태를 변경했는데 그 변경이 인증 모듈에 영향을 준다면, 이는 두 모듈이 물리적으로는 분리되어 있어도 논리적 경계가 제대로 그어지지 않았다는 신호다.
논리적 경계의 표현 형식
모듈과 컴포넌트
마크 리처즈와 닐 포드는 저서 Fundamentals of Software Architecture에서 모듈을 관련된 코드의 논리적 묶음으로, 컴포넌트를 그 모듈의 물리적 구현으로 구분한다. 이 책의 8장 컴포넌트 기반 사고에서는 논리적 컴포넌트를 먼저 정의하고 그 다음에 논리 아키텍처와 물리 아키텍처의 차이를 다루는데, 여기서 핵심 주장은 아키텍트가 처음부터 물리적 형태를 고민하기보다 사용자 스토리와 책임을 바탕으로 논리적 컴포넌트를 먼저 식별해야 한다는 것이다. 같은 책은 아키텍처의 최상위 분할 방식을 기술 기준 분할과 도메인 기준 분할로 나누는데, 계층형 아키텍처는 표현, 비즈니스, 영속성 계층처럼 기술적 역할을 기준으로 나눈 논리적 분할의 대표적 사례이고, 마이크로서비스는 카탈로그, 주문, 배송처럼 업무 도메인을 기준으로 나눈 논리적 분할이 아키텍처 스타일 자체의 철학이 된 경우다.
바운디드 컨텍스트
도메인 주도 설계에서 논리적 경계를 가장 정교하게 다루는 개념은 바운디드 컨텍스트다. 에릭 에반스가 제시하고 마틴 파울러가 정리한 바에 따르면, 바운디드 컨텍스트는 특정 도메인 모델이 적용되는 명시적인 경계다. 큰 도메인을 하나의 통일된 모델로 표현하려 할수록 조직의 서로 다른 집단이 미묘하게 다른 어휘를 사용하는 문제가 커지는데, 바운디드 컨텍스트는 이런 문제를 해결하기 위해 도메인을 여러 개의 일관된 모델 구역으로 나누고 그 구역 사이의 관계를 컨텍스트 맵으로 명시한다. 본 파넌이 저서 Implementing Domain-Driven Design에서 강조하듯, 바운디드 컨텍스트는 유비쿼터스 언어가 통용되는 개념적 경계이며, 이 경계 안에서는 용어와 모델이 일관되지만 경계를 넘어서면 같은 단어라도 다른 의미를 가질 수 있다.
바운디드 컨텍스트는 그 자체로 순수하게 논리적인 개념이라는 점이 중요하다. 마이크로소프트의 마이크로서비스 아키텍처 가이드는 이 점을 분명히 하면서, 비즈니스 마이크로서비스나 바운디드 컨텍스트를 식별했다고 해서 그것을 반드시 하나의 서비스나 하나의 도커 컨테이너로 구현해야 하는 것은 아니라고 설명한다. 하나의 바운디드 컨텍스트가 여러 개의 물리적 서비스로 구현될 수도 있고, 여러 바운디드 컨텍스트가 당분간 하나의 물리적 프로세스 안에 공존할 수도 있다.
논리적 경계가 규정하는 것
논리적 경계가 실제로 통제하는 대상은 다음과 같이 요약할 수 있다.
| 통제 대상 | 설명 |
|---|---|
| 책임의 소재 | 어떤 개념과 규칙을 누가 정의하고 변경할 권한을 갖는지 |
| 어휘의 일관성 | 같은 용어가 경계 안에서 하나의 의미로만 쓰이는지 |
| 변경의 파급 범위 | 하나의 요구사항 변경이 어디까지 코드 수정을 유발하는지 |
| 데이터의 의미 소유권 | 어떤 데이터 항목의 정의와 불변식을 누가 책임지는지 |
이 표가 보여주듯, 논리적 경계는 실행 환경이나 배포 방식과는 독립적으로 존재할 수 있는 설계상의 결정이다. 같은 논리적 경계를 유지한 채로 물리적 배치만 바꾸는 것, 예를 들어 모듈러 모놀리스의 한 모듈을 별도 서비스로 추출하는 것이 비교적 수월한 이유도 여기에 있다.
물리적 경계
정의와 성립 근거
물리적 경계는 코드가 실제로 어떤 프로세스, 어떤 컴퓨팅 자원, 어떤 저장소, 어떤 네트워크 구간에 배치되는지를 기준으로 그어지는 경계다. 로버트 마틴의 아키텍처 논의를 인용하는 여러 문헌이 설명하듯, 가장 약한 형태의 물리적 경계는 동일한 주소 공간 안에서 동적으로 링크되는 라이브러리 단위이고, 그보다 강한 경계는 별도의 로컬 프로세스이며, 가장 강한 경계는 네트워크로 분리된 별도의 서비스다. 이 경계들은 공통적으로 하나의 속성을 공유한다. 경계를 넘는 통신은 언어 내부의 함수 호출보다 비용이 크고, 실패할 수 있으며, 독립적인 배포와 버전 관리를 가능하게 한다는 점이다.
물리적 경계의 층위
프로세스와 배포 단위
가장 기본적인 물리적 경계는 프로세스 경계다. 하나의 프로세스 안에서는 메모리를 공유하고 함수 호출로 통신하지만, 프로세스가 나뉘는 순간 통신에는 직렬화, 프로세스 간 통신 수단, 별도의 메모리 보호가 필요해진다. 배포 단위 역시 물리적 경계의 한 형태다. 네이선 포드와 마크 리처즈가 공저한 Software Architecture: The Hard Parts는 이를 아키텍처 퀀텀이라는 개념으로 정식화한다. 아키텍처 퀀텀은 함께 배포되어야 하고, 높은 기능적 응집도를 가지며, 높은 정적 결합도를 갖는 소프트웨어 구성요소와 데이터의 묶음으로 정의된다. 잘 설계된 하나의 마이크로서비스가 전형적인 아키텍처 퀀텀의 예시로 제시된다. 아키텍처 퀀텀 개념이 중요한 이유는, 독립 배포성이라는 물리적 속성을 정량적으로 판단할 수 있는 기준을 제공하기 때문이다.
데이터베이스와 저장소
데이터 계층의 물리적 경계는 특히 까다로운 주제다. 크리스 리처드슨이 정리한 서비스별 데이터베이스 패턴에 따르면, 마이크로서비스 아키텍처에서는 각 서비스가 자신의 데이터베이스를 소유해야 서비스 간의 느슨한 결합과 독립적인 배포 및 확장이 가능해진다. 다만 리처드슨은 실무에서 물리적으로 완전히 분리된 데이터베이스 서버를 두는 방식만이 유일한 선택지는 아니라는 점도 함께 언급한다. 여러 서비스가 같은 데이터베이스 서버를 공유하되 각 서비스에 논리적으로 분리된 스키마나 테이블 접근 권한만 부여하는 절충적인 구성도 가능하다. 이는 물리적 경계와 논리적 경계가 데이터 계층에서도 서로 다른 층위로 작동할 수 있음을 보여주는 대표적인 사례다.
네트워크와 통신 채널
가장 강한 형태의 물리적 경계는 네트워크로 분리된 서비스 사이의 경계다. 이 경계를 넘는 통신에는 마크 리처즈와 닐 포드가 정리한 분산 컴퓨팅의 여덟 가지 오류, 즉 네트워크는 안정적이다, 지연 시간은 0이다, 대역폭은 무한하다와 같은 가정이 실제로는 성립하지 않는다는 전제가 항상 따라붙는다. 네트워크 경계는 장애를 격리하고 독립적인 확장을 가능하게 하는 대신, 지연, 부분 실패, 데이터 일관성 문제라는 대가를 요구한다.
물리적 경계가 강제하는 것
물리적 경계가 실제로 통제하는 대상은 논리적 경계와 대비해 다음과 같이 정리할 수 있다.
| 통제 대상 | 설명 |
|---|---|
| 배포의 단위 | 무엇이 함께 빌드되고 함께 릴리스되는지 |
| 장애의 격리 범위 | 하나의 프로세스나 서버의 장애가 어디까지 전파되는지 |
| 확장의 단위 | 무엇을 독립적으로 늘리거나 줄일 수 있는지 |
| 통신 비용의 성격 | 함수 호출인지, 프로세스 간 통신인지, 네트워크 호출인지 |
물리적 경계는 논리적 경계와 달리 런타임의 실체를 갖는다. 코드를 아무리 논리적으로 잘 나누어도 하나의 프로세스, 하나의 바이너리로 묶여 배포된다면 물리적으로는 여전히 하나의 단위다. 반대로 논리적으로는 뒤섞여 있는 코드라도 서로 다른 서비스로 배포되어 있다면 물리적으로는 분리된 것이다.
두 경계는 왜 일치하지 않는가
4+1 뷰 모델의 관점
필립 크루흐텐이 1995년 IEEE Software에 발표한 4+1 뷰 모델은 소프트웨어 아키텍처를 하나의 도면이 아니라 다섯 개의 동시적 관점으로 기술해야 한다고 제안했다. 이 모델은 논리 뷰, 개발 뷰, 프로세스 뷰, 물리 뷰, 그리고 이 네 뷰를 검증하는 시나리오로 구성된다. 논리 뷰는 최종 사용자에게 제공되는 기능성을 다루며 객체나 클래스의 구조로 표현되고, 물리 뷰는 소프트웨어가 하드웨어에 어떻게 매핑되는지를 다루며 시스템의 분산된 배치 형태를 보여준다. 크루흐텐이 이 두 뷰를 처음부터 분리해 제시했다는 사실 자체가, 하나의 논리 구조가 여러 물리적 배치로 실현될 수 있고 그 반대도 가능하다는 것을 전제하고 있음을 보여준다. 위키백과의 4+1 아키텍처 뷰 모델 문서 역시 이 모델이 특정 표기법에 종속되지 않는 일반적인 프레임워크라고 설명하면서, 논리 뷰와 물리 뷰가 별도의 관심사를 다룬다는 점을 강조한다.
사이먼 브라운이 만든 C4 모델도 이 4+1 뷰 모델의 논리 뷰와 물리 뷰 구분에서 영향을 받았다. C4 모델의 네 계층, 즉 컨텍스트, 컨테이너, 컴포넌트, 코드 가운데 컨테이너는 실제로 실행되어야 하는 단위, 다시 말해 물리적 배포 단위에 가까운 개념이고, 컴포넌트는 컨테이너 내부의 논리적 구조를 나타낸다.
위 다이어그램은 마이크로소프트의 마이크로서비스 아키텍처 가이드가 제시하는 예시를 도식화한 것이다. 카탈로그라는 하나의 논리적 바운디드 컨텍스트가 상품 조회 웹 API와 검색 서비스라는 두 개의 물리적 서비스로 나뉘어 배포되어 있으며, 두 서비스는 같은 데이터 저장소를 공유한다. 이는 하나의 논리적 경계가 여러 개의 물리적 경계에 대응하는 전형적인 사례다.
컴포넌트의 논리적 정의와 물리적 패키징
리처즈와 포드는 컴포넌트를 정의하는 과정을 논리 아키텍처를 만드는 단계와 물리 아키텍처로 전환하는 단계로 분리해 설명한다. 논리 아키텍처를 만드는 단계에서는 사용자 스토리를 분석해 핵심 컴포넌트를 식별하고 역할과 책임을 정리하지만, 이 단계의 산출물은 아직 배포 가능한 형태가 아니다. 그 다음 단계에서 비로소 이 논리적 컴포넌트들을 자바의 jar 파일, 닷넷의 dll, 루비의 gem처럼 실제 언어와 플랫폼이 제공하는 물리적 패키징 단위로 옮긴다. 이 두 단계를 분리해서 다루는 이유는, 물리적 제약을 먼저 고려하면 설계자가 책임과 응집도가 아니라 배포 편의성을 기준으로 컴포넌트를 나누게 되어 결과적으로 응집도가 낮은 설계에 도달하기 쉽기 때문이다.
경계 사이의 대응 관계 유형
CodeOpinion의 데릭 코마틴은 논리적 경계와 물리적 경계 사이에 다음과 같은 대응 관계가 가능하다고 정리한다.
- 하나의 논리적 경계가 하나의 물리적 경계와 정확히 일치하는 경우
- 하나의 논리적 경계가 여러 개의 물리적 경계로 나뉘어 구현되는 경우
- 하나의 물리적 경계 안에 여러 개의 논리적 경계가 함께 담기는 경우
그는 마이크로서비스 운동이 이 세 가지 가능성 중 첫 번째, 즉 논리, 개발, 물리 뷰가 모두 일치해야 한다는 암묵적 전제를 지나치게 당연한 것으로 만들었다고 지적한다. 그 결과 불필요한 배포 복잡성, 버전 관리 부담, 데이터 중복이라는 비용을 감수하면서까지 모든 논리적 경계를 곧바로 별도의 서비스로 쪼개는 경향이 생겼다는 것이다.
아키텍처 스타일별 경계 배치
계층형 모놀리스: 하나의 물리적 경계, 다수의 논리적 경계
전통적인 계층형 아키텍처는 표현 계층, 비즈니스 계층, 영속성 계층이라는 논리적 경계를 갖지만, 이 계층들은 대개 하나의 배포 단위, 하나의 프로세스로 묶여 실행된다. 즉 논리적 경계는 여러 개 존재하지만 물리적 경계는 단 하나다. 이 방식의 장점은 계층 사이의 호출이 함수 호출 수준으로 저렴하다는 것이고, 단점은 계층 사이의 의존 방향이 강제되지 않으면 논리적 경계가 쉽게 침식된다는 것이다. Baeldung의 소프트웨어 경계 설명에 따르면, 계층형 구조에서 각 계층은 역할상 독립적으로 설계되지만 상위 계층이 하위 계층에 의존하는 구조적 특성 때문에 계층들이 논리적으로는 분리되어 있어도 완전히 결합이 끊어져 있지는 않다.
모듈러 모놀리스: 논리적 경계를 강화한 절충안
모듈러 모놀리스는 계층형 모놀리스의 이런 약점을 보완하기 위해 등장한 절충적 스타일이다. 카밀 그리벡은 모듈러 모놀리스를 모듈 방식으로 설계된 모놀리스 시스템에 붙인 명시적인 이름이라고 정의하면서, 모놀리스라는 단어 자체가 나쁜 설계를 의미하지는 않는다고 강조한다. 그가 정리한 핵심 원칙은 다음과 같다.
- 모듈은 기술적 계층이 아니라 업무 도메인을 기준으로 나뉜 수직 슬라이스로 구성한다
- 모듈 사이의 통신은 반드시 명시적으로 정의된 인터페이스를 통해서만 이루어져야 한다
- 기본적으로 모든 것을 비공개로 두고, 꼭 필요한 것만 외부에 공개한다
그리벡은 모듈러 모놀리스가 도메인 주도 설계의 바운디드 컨텍스트 개념을 모듈 단위로 그대로 적용할 수 있는 구조라고 설명하며, 이렇게 설계된 모듈은 필요할 때 별도의 물리적 서비스로 비교적 수월하게 추출될 수 있다고 덧붙인다. 다만 코드오피니언과 브이펑션 등 여러 실무 문헌이 공통적으로 지적하듯, 모듈 사이에 데이터베이스 테이블을 직접 조인하거나 모듈 경계를 넘나드는 임포트를 허용하면 이름만 모듈러 모놀리스일 뿐 내부적으로는 여전히 빅 볼 오브 머드가 될 위험이 있다.
마이크로서비스: 논리적 경계와 물리적 경계의 합치를 지향
마이크로서비스 아키텍처는 논리적 경계와 물리적 경계를 최대한 일치시키려는 스타일이다. 샘 뉴먼은 저서 Building Microservices에서 정보 은닉, 결합도, 응집도, 도메인 주도 설계가 서비스의 올바른 경계를 찾는 데 핵심적인 역할을 한다고 설명하며, 서비스 경계를 정보 은닉의 경계이자 독립적으로 배포 가능한 단위로 정의한다. 크리스 리처드슨이 정리한 마이크로서비스 패턴 언어 역시 각 서비스가 작고 이해하기 쉬운 하위 도메인 하나 또는 소수를 담당해야 팀의 자율성과 빠른 배포 파이프라인이라는 이점을 얻을 수 있다고 설명한다.
다음 표는 세 아키텍처 스타일에서 논리적 경계와 물리적 경계가 어떻게 배치되는지를 요약한 것이다.
| 아키텍처 스타일 | 논리적 경계의 개수 | 물리적 경계의 개수 | 전형적 위험 |
|---|---|---|---|
| 계층형 모놀리스 | 다수 (계층 단위) | 하나 | 계층 간 결합의 침식 |
| 모듈러 모놀리스 | 다수 (도메인 단위) | 하나 또는 소수 | 모듈 간 경계의 침식 |
| 마이크로서비스 | 다수 (도메인 단위) | 논리적 경계와 대체로 일치 | 잘못된 경계의 조기 고정과 분산 비용 |
경계 불일치가 낳는 문제
분산 모놀리스
논리적 경계와 물리적 경계 사이의 불일치가 낳는 가장 널리 알려진 문제는 분산 모놀리스다. 브이펑션의 정리에 따르면, 분산 모놀리스는 여러 서비스가 물리적으로는 각각 다른 컨테이너에서 실행되고 서로 다른 저장소에 코드를 두고 있지만, 실제로는 독립적으로 개발하거나 테스트하거나 배포할 수 없는 상태를 가리킨다. 이 문제는 대개 기존 모놀리스의 코드 경계를 그대로 따라 서비스를 분리하는 이른바 리프트 앤 시프트 방식의 분해에서 비롯되며, 업무 도메인이 아니라 기존 코드 구조를 기준으로 나누다 보니 결합이 그대로 이전되는 것이 근본 원인으로 지목된다. 토마스 툴카는 이를 더 근본적으로 정리하는데, 그는 논리적으로는 모놀리스이면서 물리적으로는 모놀리스가 아닌 시스템을 분산 모놀리스라고 부르고, 마이크로서비스는 물리적 모놀리스 문제만 해결할 뿐 논리적 모놀리스, 즉 얽혀 있는 설계 자체를 해결해 주지는 않는다고 지적한다.
공유 데이터베이스 안티패턴
데이터 계층에서 발생하는 대표적인 경계 불일치는 여러 서비스가 하나의 데이터베이스 스키마를 직접 조회하고 수정하는 공유 데이터베이스 패턴이다. 크리스 리처드슨은 이를 서비스별 데이터베이스 패턴에 반대되는 안티패턴으로 명시하며, 한 서비스의 스키마 변경이 다른 여러 서비스를 동시에 깨뜨릴 수 있다는 점을 문제로 지적한다. 물리적으로는 별도의 서비스로 배포되어 있어도 데이터 계층의 물리적 경계가 서비스 경계와 일치하지 않으면 서비스 간 결합은 논리적 경계와 무관하게 강하게 유지된다.
과도한 물리적 분할의 비용
반대 방향의 문제도 존재한다. 모든 논리적 경계를 곧바로 별도의 물리적 서비스로 만들면, 논리적으로는 굳이 나눌 필요가 없던 개념까지 네트워크 경계 너머로 흩어지게 되어 지연, 장애 전파, 데이터 일관성 관리라는 비용이 발생한다. CodeOpinion은 이를 두고 물리적 경계, 개발 경계, 논리적 경계가 항상 같아야 한다는 전제 자체가 불필요한 배포 복잡성과 데이터 중복을 만들어 낸다고 지적한다. 마틴 파울러 역시 모놀리스 우선 접근에서, 새 프로젝트를 곧바로 마이크로서비스로 시작한 사례들이 대체로 심각한 어려움에 빠졌다고 관찰하면서, 안정적인 바운디드 컨텍스트를 미리 파악하기 어려운 초기 단계에서 성급하게 물리적 경계를 확정하는 것을 경계해야 한다고 말한다.
조직 구조와 경계: 콘웨이의 법칙
콘웨이의 법칙 개요
멜빈 콘웨이는 1968년 발표한 논문에서, 시스템을 설계하는 조직은 그 조직의 의사소통 구조를 그대로 복제한 설계를 만들어 낼 수밖에 없다고 주장했다. 위키백과의 콘웨이의 법칙 문서는 이 원리의 근거를 다음과 같이 설명한다. 하나의 제품이 제대로 동작하려면 그 구성 요소를 만드는 사람들이 서로 소통하며 호환성을 맞춰야 하므로, 결과적으로 시스템의 기술적 구조는 그 시스템을 만든 조직의 사회적 경계를 그대로 반영하게 된다는 것이다. 이는 소프트웨어 아키텍처의 물리적 경계, 특히 서비스나 배포 단위의 경계가 순수하게 기술적인 결정만은 아니라는 점을 보여준다.
역콘웨이 전략
콘웨이의 법칙을 인지한 조직들은 이를 반대로 활용하기도 한다. 원하는 아키텍처를 먼저 설계한 다음, 그 아키텍처와 같은 모양으로 팀 구조를 의도적으로 재편하는 접근을 역콘웨이 전략이라고 부른다. 조 라이스는 이를 데이터 모델링의 맥락에서 설명하면서, 느슨하게 결합된 모듈형 시스템을 원한다면 각 구성요소에 대해 완전한 자율성을 가진 소규모 팀을 구성하는 것이 현대적인 마이크로서비스 아키텍처나 데이터 메시 접근의 핵심 원리라고 정리한다.
팀 경계와 아키텍처 경계의 정렬
콘웨이의 법칙이 물리적 경계 설계에 주는 실무적 함의는, 서비스나 모듈의 물리적 경계를 그을 때 그 경계를 유지하고 운영할 팀의 경계도 함께 고려해야 한다는 것이다. 팀 경계와 아키텍처 경계가 어긋나면, 하나의 서비스를 여러 팀이 함께 소유하게 되거나 하나의 팀이 여러 서비스에 걸쳐 조율해야 하는 상황이 반복되면서 의사소통 비용이 아키텍처의 물리적 분리로 얻으려 했던 이점을 상쇄해 버릴 수 있다.
위 다이어그램은 역콘웨이 전략이 지향하는 이상적인 상태, 즉 팀의 경계와 물리적 서비스 경계가 일대일로 정렬된 모습을 보여준다.
경계를 시각화하는 방법
C4 모델의 컨테이너와 컴포넌트
사이먼 브라운이 만든 C4 모델은 논리적 경계와 물리적 경계를 서로 다른 다이어그램 계층으로 명시적으로 구분해 시각화하는 도구다. 공식 사이트인 c4model.com에 따르면 이 모델은 시스템 컨텍스트, 컨테이너, 컴포넌트, 코드라는 네 단계의 계층적 다이어그램과 시스템 랜드스케이프, 동적 다이어그램, 배포 다이어그램이라는 보조 다이어그램으로 구성되며, 표기법과 도구에 종속되지 않는다는 것을 원칙으로 삼는다. 이 가운데 컨테이너 다이어그램은 실행되어야 하는 단위, 즉 애플리케이션이나 데이터 저장소처럼 물리적 실체에 가까운 요소를 보여주고, 컴포넌트 다이어그램은 하나의 컨테이너 내부에 존재하는 논리적 구조를 보여준다. 위키백과의 C4 모델 문서가 밝히듯, 브라운은 이 모델을 만들 때 UML과 크루흐텐의 4+1 뷰 모델의 뿌리에서 영감을 받았으며, 리처즈와 포드의 Fundamentals of Software Architecture 역시 C4 모델을 참고 문헌으로 인용하고 있다.
컨텍스트 매핑
도메인 주도 설계에서 여러 바운디드 컨텍스트, 즉 여러 논리적 경계 사이의 관계를 시각화하는 도구는 컨텍스트 맵이다. 마틴 파울러는 바운디드 컨텍스트에 대한 글에서, 전략적 설계는 바운디드 컨텍스트를 나누는 것에서 그치지 않고 그 사이의 관계를 명시적으로 표현하는 것까지 포함해야 하며, 이를 위해 컨텍스트 맵을 그리는 것이 일반적이라고 설명한다. 컨텍스트 맵은 오픈 호스트 서비스, 공개 언어, 부패 방지 계층과 같은 기술적 통합 패턴과, 두 컨텍스트를 담당하는 팀 사이의 관계, 예를 들어 고객과 공급자 관계인지 동반자 관계인지를 함께 표현한다. 이는 논리적 경계의 시각화가 결국 조직 구조, 즉 물리적 경계와 완전히 무관할 수 없다는 점을 다시 한번 보여준다.
설계 원칙과 실무 지침
논리적 경계를 먼저 설계한다
여러 문헌이 공통적으로 제시하는 첫 번째 원칙은 물리적 형태를 정하기 전에 논리적 경계를 먼저 확정하라는 것이다. 리처즈와 포드는 사용자 스토리와 책임 분석을 통해 논리적 컴포넌트를 먼저 식별한 다음에야 물리적 패키징으로 넘어가야 한다고 제안하며, 마틴 파울러의 모놀리스 우선 접근 역시 안정적인 바운디드 컨텍스트, 즉 논리적 경계를 충분히 파악하기 전에는 물리적으로 분산된 마이크로서비스 구조를 강제로 확정하지 말라고 권고한다. 그 이유는 논리적 경계가 물리적 경계보다 훨씬 자주, 그리고 훨씬 저렴하게 수정될 수 있어야 하기 때문이다.
물리적 분할은 필요와 트레이드오프에 따라 결정한다
두 번째 원칙은 물리적 경계를 나누는 결정에는 반드시 구체적인 필요와 트레이드오프 분석이 뒤따라야 한다는 것이다. 물리적 분할이 필요한 전형적인 이유로는 서로 다른 확장 요구, 서로 다른 배포 주기, 서로 다른 신뢰성 요구, 규제나 데이터 주권상의 요구 등이 꼽힌다. 반대로 단지 논리적으로 구분되어 있다는 이유만으로 물리적으로도 분리해야 한다는 결론이 자동으로 따라오지는 않는다. 마이크로소프트의 가이드가 강조하듯, 중요한 것은 논리적 단위가 코드와 상태를 독립적으로 버전 관리하고 배포하고 확장할 수 있는 자율성을 갖는지 여부이며, 이 자율성이 반드시 별도의 프로세스나 컨테이너를 요구하지는 않는다.
아키텍처 퀀텀과 독립 배포성
포드, 리처즈, 사달라지, 데그하니가 공저한 Software Architecture: The Hard Parts는 물리적 분할의 단위를 판단하는 구체적인 기준으로 아키텍처 퀀텀 개념을 제시한다. 함께 배포되어야 하고 기능적으로 응집되어 있으며 정적으로 강하게 결합된 구성요소의 묶음이 하나의 아키텍처 퀀텀을 이룬다. 이 개념을 적용하면, 논리적으로는 분리되어 보이는 두 컴포넌트라도 실제로는 항상 함께 배포되고 강하게 결합되어 있다면 아직 별도의 물리적 경계로 나눌 준비가 되지 않았다고 판단할 수 있고, 반대로 독립적인 배포 이력과 낮은 결합도를 보인다면 물리적으로 분리할 근거가 충분하다고 판단할 수 있다. 결국 논리적 경계와 물리적 경계를 둘러싼 모든 논의는, 두 경계가 언젠가 일치해야 한다는 강박이 아니라 지금 이 순간의 결합도와 변경 빈도를 기준으로 어느 층위의 경계가 필요한지를 계속 재평가하는 문제로 귀결된다.
참고 자료
- Kruchten, Philippe (1995), Architectural Blueprints: The “4+1” View Model of Software Architecture, IEEE Software
- Conway, Melvin E. (1968), How Do Committees Invent?, Datamation
- Evans, Eric (2003), Domain-Driven Design: Tackling Complexity in the Heart of Software, Addison-Wesley
- Vernon, Vaughn (2013), Implementing Domain-Driven Design, Addison-Wesley
- Newman, Sam (2021), Building Microservices: Designing Fine-Grained Systems, 2nd Edition, O’Reilly Media
- Richards, Mark; Ford, Neal (2020), Fundamentals of Software Architecture: An Engineering Approach, O’Reilly Media
- Ford, Neal; Richards, Mark; Sadalage, Pramod; Dehghani, Zhamak (2021), Software Architecture: The Hard Parts: Modern Trade-Off Analyses for Distributed Architectures, O’Reilly Media
- Fowler, Martin (2014), Bounded Context, martinfowler.com
- Fowler, Martin (2015), MonolithFirst, martinfowler.com
- Brown, Simon, The C4 Model for Visualising Software Architecture, c4model.com
- Richardson, Chris, Pattern: Database per Service, microservices.io
- Richardson, Chris, Microservice Architecture Pattern, microservices.io
- Grzybek, Kamil (2019), Modular Monolith: A Primer, kamilgrzybek.com
- Comartin, Derek (2022), Microservices Gets It Wrong Defining Service Boundaries, CodeOpinion
- Microsoft (2018), Logical Architecture Versus Physical Architecture, Microsoft Learn (.NET Microservices Architecture for Containerized .NET Applications)
- Wikipedia contributors, 4+1 Architectural View Model, Wikipedia
- Wikipedia contributors, C4 Model, Wikipedia
- Wikipedia contributors, Conway’s Law, Wikipedia