Book Notes

[개발서적] 도메인 주도 설계 첫걸음 1부(ch3~4) 요약 (2)

feel2 2026. 1. 10. 16:06

Ch3. 도메인 복잡성 관리


 

프로젝트의 성공을 보장하려면 소프트웨어 엔지니어로부터 도메인 전문가에 이르기까지 모든 이해관계자가 의사소통에 사용할 수 있는 유비쿼터스 언어를 개발하는 것이 중요하다.

 

우리의 목표는 유비쿼터스 언어를 사용하여 소프트웨어 설계의 의사결정을 내리는 것이기 때문에 언어는 명확하고 일관성이 있어야 한다.

그러나 같은 비즈니스 도메인이어도 도메인 전문가마다 서로 다른 모델을 사용할 수 있다. 예제를 살펴보자.

 

[일관성 없는 모델]

2장의 텔레마케팅 회사의 예를 보자. 회사의 마케팅 부서는 온라인 광고를 통해 리드(lead)를 생성한다.

영업 부서는 잠재고객이 제품이나 서비스를 구매하도록 유도하는 역할을 하며, 이것이 그림 3-1에 나와 있다.

 

그림 3-1. 비즈니스 도메인 예시: 텔레마케팅 회사

 

 

도메인 전문가의 언어를 살펴보면 특이한 점이 있다.

리드(lead)라는 용어가 마케팅과 영업 부서에서 서로 다른 의미로 사용한다.

  • 마케팅 부서: 누군가가 제품 중 하나에 관심이 있다는 알림, 잠재고객의 연락처 정보를 수신하는 이벤트를 리드로 간주함
  • 영업 부서: 영업 프로세스의 전체 수명주기, 리드는 단순한 이벤트가 아니라 장기적으로 진행되는 과정

텔레마케팅 회사의 경우 유비쿼터스 언어를 어떻게 공식화할까?

 

이 문제에 대한 전통적인 솔루션은 모든 종류의 문제에 사용할 수 있는 단일 모델을 설계하는 것이다.

그러나 ERD를 설계하더라도 너무 복잡하면 관리가 어려워 진다.

 

그림 3-2. 전사적 엔티티 관계 다이어그램

 

또 다른 솔루션은 ‘마케팅 리드’, ‘영업 리드’와 같이 문맥상 정의에 문제가 있는 용어 앞에 접두사를 추가하는 것이다.

그러나 이 방식도 그렇게 적합하지는 않다.

 

이러한 문제를 해결하기 위해 도메인 주도 설계 패턴 중 하나인 바운디드 컨텍스트라는 주제를 살펴보자.

 

[바운디드 컨텍스트란 무엇인가?]

도메인 주도 설계에서 솔루션은 간단하다.

유비쿼터스 언어를 여러 개의 작은 언어로 나눈 다음, 각 언어를 적용할 수 있는 명시적인 바운디드 컨텍스트(bounded context)에 할당하면 된다.

 

앞의 예에서 마케팅과 영업이라는 두가지 바운디드 컨텍스트를 식별할 수 있다.

그림 3-3에서 보듯이 ‘리드’라는 용어는 두 가지 바운디드 컨텍스트에 모두 존재한다.

 

그림 3-3. 유비쿼터스 언어를 바운디드 컨텍스트로분할하여 인관성이 없는 문제를 해결

 

어떤 의미에서 용어 충돌과 암시적 컨텍스트는 적당한 규모의 모든 비즈니스에 내재된 부분이다.

바운디드 컨텍스트 패턴을 사용하면 컨텍스트를 명시적이고, 중요한 비즈니스 도메인의 요소로 모델링 가능하다.

 

모델 경계

모델은 실제 세계의 복사본이 아니라 복잡한 시스템을 이해하는데 도움을 주기 위해 구조화한 것이다.

모델은 모델의 경계(바운디드 컨텍스트)를 정의하는 것이 모델링 프로세스의 본질적인 부분이다.

 

하나의 바운디드 컨텍스트의 유비쿼터스 언어는 다른 바운디드 컨테긋트 범위와는 완전히 관련이 없다.

바운디드 컨텍스트는 유비쿼터스 언어의 일관성이 유지되는 경계다.

 

정제된 유비쿼터스 언어

유비쿼터스 언어는 바운디드 컨텍스트 경계 안에서만 보편적으로 적용된다.

또한 유비쿼터스 언어는 바운디드 컨텍스트에 포함된 모델을 설명하는데만 집중한다.

 

바운디드 컨텍스트 범위

비즈니스 도메인을 모델링하기 위해 우리는 모델을 분리하고, 각 세분화된 모델을 적용 가능한 컨텍스트(바운디드 컨텍스트)를 엄격하게 정의해야 한다.

또한 그림 3-4와 같이 모델을 더 작은 바운디드 컨텍스트로 분해할 수도 있다.

 

그림 3-4. 더 작은 바운디드 컨텍스트

 

유비쿼터스 언어의 범위(바운디드 컨텍스트)를 정의하는 것은 전략적인 설계 의사결정이다.

경계는 비즈니스 도메인의 고유한 컨텍스트에 따라 넓힐 수도 있고, 세분화하여 좁힐 수도 있다.

 

바운디드 컨텍스트는 상황에 따라 커질수도, 작아질수도 있다.

따라서 모델을 유용하게 유지하고, 바운디드 컨텍스트의 크기를 비즈니스 요구사항과 조직의 제약사항에 맞춰라.

 

한가지 주의할 점은 응집된 기능을 여러 바운디드 컨텍스트로 분할하는 것이다.

 

이러한 비효율적인 분해를 피하기 위해 하위 도메인을 찾고, 같은 데이터에서 작동하는 응집된 유스케이스의 집합을 식별하되, 그것을 여러 개의 바운디드 컨텍스트로 분해하지 마라.

 

[바운디드 컨텍스트 대 하위 도메인]

 

하위 도메인

기업의 비즈니스 전략을 이해하려면 비즈니스 도메인을 분석해야 한다.

도메인 주도 설계 방법론에 따르면 분석 단계에는 다양한 하위 도메인(핵심, 지원, 일반)을 식별하는 작업이 포함된다.

그것이 바로 조직이 일하고 경쟁 전략을 계획하는 방식이다.

 

소프트웨어 엔지니어로서 우리는 요구사항을 정의하지 않는다.

대신 하위 도메인을 식별하기 위한 비즈니스 도메인을 분석한다.

 

바운디드 컨텍스트

반면에 바운디드 컨텍스트는 소프트웨어 엔지니어에 의해 설계된다.

우리는 비즈니스 도메인을 더 작고 관리 가능한 문제 도메인으로 어떻게 나눌지 정한다.

 

하위 도메인과 바운디드 컨텍스트 사이의 상호작용

비현식적이지만, 이론적으로 단일 모델이 전체 비즈니스 도메인에 적용될 수 있다.

그림 3-5와 같이 소규모 시스템의 경우 그렇다.

 

그림 3-5. 모놀리식 바운디드 컨텍스트

 

모델이 충돌하면 3-6과 같이 도메인 전문가의 모델을 따라 시스템을 바운디드 컨텍스트로 분해할 수 있다.

 

그림 3-6. 유비쿼터스 언어의 일관성에 따라 나눈 바운디드 컨텍스트

 

모델이 여전히 크고 유지보수가 어려운 경우 더 작은 바운디드 컨텍스트로 분해할 수 있다.

예를 들어 각 하위 도메인에 대한 바운디드 컨텍스트로 나눌 수 있다.

 

그림 3-7. 하위 도메인 경계에 맞춰 나눈 바운디드 컨텍스트

 

어느 쪽이든 이것은 설계에 대한 의사결정이다.

 

중요한 것은 하위 도메인은 발견하고 바운디드 컨텍스트는 설계한다는 점이다.

즉, 하위 도메인은 비즈니스 전략에 의해 정의된다.

그러나 바운디드 컨텍스트는 소프트웨어 엔지니어가 특정 문제를 해결하기 위해 설계한다.

 

[경계]

바운디드 컨텍스트 패턴은 물리적 경계소유권 경계를 규정하기 위한 도메인 주도 설계 도구다.

 

물리적 경계

바운디드 컨텍스트는 모델 경계뿐만 아니라 이를 구현하는 시스템의 물리적 경계 역할도 한다.

각 바운디드 컨텍스트는 개별 서비스/프로젝트로 구현돼야 한다.

 

즉, 구현, 진화, 버전 관리를 각각의 다른 바운디드 컨텍스트와 독립적으로 해야 한다.

바운디드 컨텍스트 간의 명확한 물리적 경계를 통해, 각 바운디드 컨텍스트를 요구사항에 가장 적합한 기술 스택으로 구현할 수 있다.

 

앞에서 논의한 바와 같이 바운디드 컨텍스트는 여러 하위 도메인을 포함할 수 있다.

이러한 경우 바운디드 컨텍스트는 물리적 경계고, 하위 도메인은 논리적 경계다.

 

소유권 경계

팀 간의 작업 분배는 바운디드 컨텍스트 패턴을 사용하여 내릴 수 있는 또 다른 전략적 의사결정이다.

바운디드 컨텍스트는 한 팀에서만 구현, 발전, 유지 관리를 해야 한다.

 

또한 각각의 팀은 서로 다른 바운디드 컨텍스트로 분리된 시스템과 연동하기 위해서는 통신 프로토콜을 정의해야 한다.

바운디드 컨텍스트는 한 팀이 여러 개 소유할 수도 있다.

 

그림 3-8. 하나의 팀은 여러 바운디드 컨텍스트를 소유할 수 있다.

 

[실생활의 바운디드 컨텍스트]

소프트웨어 엔지니어는 도메인 전문가가 다양한 비즈니스 엔티티와 프로세스에 대해 어떻게 생각하는지 항상 의식해야 한다.

 

시맨틱 도메인

도메인 주도 설계의 바운디드 컨텍스트는 시멘틱 도메인의 사전적 개념에 기반한다고 볼 수 있다.

시맨틱 도메인(semantic domain)의미 영역과 해당 의미를 전달하기 위해 사용하는 단어 영역으로 구분한다.

예를 들어 모니터, 포트, 프로세서라는 단어는 소프트웨어와 하드웨어 엔지니어링 시맨틱 도메인에서 서로 다른 의미를 갖는다.

 

과학

과학의 경우 모든 경우에 들어맞는 과학적 이론은 없다.

다른 이론은 다른 맥락 안에서 유용하다.

 

예를 들어 뉴턴의 운동 법칙에 따르면 공간과 시간은 절대적이다.

아인슈타인의 상대성 이론에서는 공간과 시간은 더 이상 절대적이지 않고 관찰자에 따라 다르다.

 

두 모델이 모순되는 것처럼 보이지만 둘 다 적절한 (바운디드) 컨텍스트에서 유용하다.

 

[결론]

도메인 전문가의 멘탈 모델에 내재된 충돌을 발견할 때마다 유비쿼터스 언어를 여러개 바운디드 컨텍스트로 분해해야 한다.

 

하위 도메인이 발견되면 바운디드 컨텍스트도 설계한다.

도메인을 바운디드 컨텍스트로 나누는 것은 전략적 설계의 의사결정이다.

 

바운디드 컨텍스트는 시스템을 서비스, 하위 시스템 등의 물리적 구성요소로 분해한다.

각 바운디드 컨텍스트의 수명주기는 서로 독립적이다.

 

Ch4. 바운디드 컨텍스트 연동


 

바운디드 컨텍스트 패턴은 유비쿼터스 언어의 일관성을 유지할 뿐만 아니라 모델링도 가능하게 한다.

모델의 목적, 즉 경계를 명시하지 않고는 모델을 구축할 수 없다.

경계가 언어의 책임을 구분 짓는다.

 

바운디드 컨텍스트는 서로 독립적으로 발전할 수는 있지만, 상호작용해야 한다.

바운디드 컨텍스트 사이에는 항상 접점이 있는데, 이를 컨트랙트(contract)라고 한다.

 

컨트랙트의 필요성은 바운디드 컨텍스트의 모델과 언어의 차이에서 비롯된다.

각 컨트렉트는 하나 이상의 당사자에게 영향을 끼치므로 서로 조율해서 컨트랙트를 정의해야 한다.

 

[협력형 패턴 그룹]

협력형(cooperation) 그룹의 패턴은 소통이 잘 되는 팀에서 구현된 바운디드 컨텍스트와 관련이 있다.

이 패턴이 적합한 요건은 팀의 커뮤니케이션과 협업의 수준이다.

 

파트너십 패턴

파트너십(partnership) 모델에서 바운디드 컨텍스트 간의 연동은 애드훅(ad-hoc) 방식으로 조정한다.

한 팀은 다른 팀에게 API의 변경을 알리고 다른 팀은 충돌 없이 이를 받아들인다.

 

그림 4-1. 파트너십 모델

 

여기서 연동의 조정은 양방향에서 한다.

양 팀은 서로 다른 언어를 사용할 수도 있으며, 적절한 솔루션을 택할 수도 있다.

연동의 문제는 양 팀 모두 협력하여 해결한다.

 

이런 패턴은 동기화와 커뮤니케이션의 어려움 때문에 지리적으로 떨어져 있는 팀에게는 적합하지 않을 수 있다.

 

공유 커널 패턴

바운디드 컨텍스트가 모델의 경계임에도 불구하고, 여전히 하위 도메인의 동일 모델 혹은 그 일부가 여러 다른 바운디드 컨텍스트에서 구현되는 경우가 있다.

공유 커널(shared kernel)과 같은 모델은 모든 바운디드 컨텍스트의 필요에 따라 설계된다.

 

사용자의 권한을 관리하는 모델을 내부에서 개발해 사용하는 기업 시스템을 예로 들어보자.

각각의 사용자는 권한을 직접 부여받거나 소속된 단위 조직에서 상속받는다.

각 바운디드 콘텍스트는 권한 모델을 수정할 수 있고, 이 변경은 이 모델을 사용하는 모든 다른 바운디드 컨텍스트에 영향을 준다.

 

그림 4-2. 공유 커널

공유 범위

공유 커널은 바운디드 컨텍스트 간에 제공될 의도가 있는 연동 관련 컨트랙트와 자료구조만으로 구성하는 것이 이상적이다.

 

구현

공유 커널은 소스코드의 모든 변경이 이를 사용하는 모든 바운디드 컨텍스트에 즉시 반영되도록 구현한다.

어떤 방식이든 공유 커널에 대한 변경이 생길 때마다 영항을 받는 모든 바운디드 컨텍스트와 연동 테스트를 추가해야 한다.

 

공유 커널을 사용해야 하는 경우

공유 커널 패턴의 적용 여부를 결정하는 가장 중요한 기준은 중복 비용과 조율 비용의 비율이다.

이 패턴은 중복 비용이 조율 비용보다 클 경우에만 적용해야 한다.

 

변경이 잦을수록 통합 비용이 높아진다.

그러므로 자연스럽게 공유 커널은 핵심 하위 도메인처럼 많이 변하는 하위 도메인에 적용된다.

 

공유 커널을 사용하는 데는 명분이 필요하다.

예를 들어 지리적인 제약이나 조직의 정치적 문제로 커뮤니케이션 또는 협업이 어려워서 파트너십 패턴을 구현하기 어려울 때를 볼 수 있다.

또 다른 예로는 레거시 시스템을 점진적으로 현대화하는 경우다.

 

결국, 공유 커널은 동일 팀에서 소유하고 구현한 바운디드 컨텍스트를 연동하는 경우에 잘 맞는다.

 

[사용자-제공자 패턴 그룹]

협업 패턴 중에 두번째로 살펴 볼 그룹은 사용자-제공자(customer-supplier) 패턴 그룹이다.

그림 4-3에서는 제공자는 사용자에게 서비스를 제공한다.

서비스 제공자는 ‘업스트림’이고, 고객 또는 사용자는 ‘다운스트림’이다.

 

그림 4-3. 사용자-제공자 관계

 

 

협력 그룹의 경우와는 다르게 양 팀은 서로 독립적으로 성공할 수 있다.

그러나 대부분의 경우 업스트림 또는 다운스트림의 팀이 연동 컨트랙트를 주도하는 권력의 불균형이 존재한다.

 

순응주의자 패턴

힘의 균형이 서비스를 제공하는 업스트림에 있는 경우다.

사용자의 요구를 지원할 동기가 없는 경우가 그렇다.

 

그림 4-4. 순응주의자 관계

 

업스트림 팀이 노출한 컨트랙트가 예를 들어 산업 표준이거나 잘 구축된 모델 또는 다운스트림 팀의 요건에 충분하다면 다운스트림 팀이 자율성의 일부를 포기할 수 있다.

 

충돌 방지 계층 패턴

순응주의자 패턴에서 힘의 균형은 업스트림 서비스에 치우쳐 있다.

그러나 다운스트림 서비스가 이에 순응하지 않을 경우 충돌 방지 계층을 통해 스스로의 필요에 맞게 가공할 수 있다.

 

그림 4-5. 충돌 방지 계층을 통한 연동

 

충돌 방지 계층(ACL: anticorruption layer) 패턴은 제공자의 모델을 따르는 것을 원치 않거나 순응에 필요한 노력이 가치가 없는 경우를 다룬다.

 

다음과 같은 경우 이에 해당할 수 있다.

  • 다운스트림 바운드디 컨텍스트가 핵심 하위 도메인을 포함할 경우
  • 업스트림 모델이 사용자의 요건에 비효율적이거나 불편한 경우
  • 제공자가 컨트렉트를 자주 변경하는 경우

 

오픈 호스트 서비스 패턴

이 패턴은 힘이 사용자 측에 있는 경우를 말한다.

제공자는 사용자를 보호하고 가능한 최고의 서비스를 제공하는데 관심이 있다.

 

구현 모델의 변경으로부터 사용자를 보호하기 위해 업스트림 제공자는 퍼블릭 인터페이스와 구현 모델을 분리한다.

이를 통해 외부에 제공되는 퍼블릭 모델과 그 내부 구현을 다른 속도로 발전시킬 수 있다.

 

그림 4-6. 오픈 호스트 서비스를 통한 연동

 

위 그림에서 제공자의 퍼블릭 인터페이스는 자신의 유비쿼터스 언어를 따르는 대신, 연동 지향 언어(integration-oriented language)를 통해 프로토콜을 노출하려 한다.

이런 퍼블릭 프로토콜을 공표된 언어(published language)라고 한다.

 

한편, 오픈 호스트 서비스(OHS) 패턴은 충돌 방지 계층 패턴의 반대다.

즉, 사용자 대신 제공자내부 모델 번역을 구현한다.

 

또한 연동 모델을 분리하면 업스트림 바운디드 컨텍스트는 이미 공표된 언어의 여러 버전을 동시에 노출할 수 있어서 사용자가 점진적으로새로운 버전으로 이관할 수 있게 된다.

 

그림 4-7. 여러 버전의 공표된 언어를 노출하는 오픈 호스트 서비스

 

[분리형 노선]

마지막으로 살펴볼 협업 옵션은 전혀 협력하지 않는 것이다.

분리형 노선(separated ways) 패턴에는 팀에 헙업 의지가 없거나 협업할 수 없는 경우와 같이 다양한 이유가 있다.

 

커뮤니케이션 이슈

협업을 회피하는 일반적인 이유는 조직의 규모와 내부 정치 요인으로 인한 커뮤니케이션의 어려움 때문이다.

이럴 경우 각자의 길을 가는 것이 더 비용 효과적이다.

 

일반 하위 도메인

중복된 하위 도메인의 특성도 협업 없이 분리된 길을 가야할 수 있다.

예를 들어 로깅 프레임워크가 있다.

 

모델의 차이

모델이 너무 다르다면 순응주의자 관계가 불가능하고, 충돌 방지 계층 구현하는 것이 더 비용이 클 수 있다.

 

[컨텍스트 맵]

시스템의 바운디드 컨텍스트 간의 연동 패턴을 분석하면 다음과 같은 컨텍스트 맵을 그릴 수 있다.

 

그림 4-8. 컨텍스트 맵

 

컨텍스트 맵은 시스템의 바운디드 컨텍스트와의 연동을 시각적으로 표현한다.

컨텍스트 맵은 다음과 같은 전략적 통찰력을 제공한다.

  • 거시적 설계관점: 시스템의 구성요소나 구현하는 모델의 개요를 제공한다.
  • 커뮤니케이션 패턴: 어떤 팀이 협력하고, 충돌 방지 계층과 분리형 노선 패턴과 같은 연동 패턴의 선호도를 보여준다.
  • 조직적 문제: 조직적 문제에 대한 통찰력을 제공한다.

 

유지보수

컨텍스트 맵은 프로젝트 초기부터 도입해서 새로운 바운디드 컨텍스트와 기존 요소에 대한 수정을 반영하는 것이 이상적이다.

컨텍스트 맵은 여러 팀이 작업한 정보가 담겨 있기 때문에 같이 유지보수하는 것이 좋다.

 

한계

컨텍스트 맵을 작성하는 것은 어려운 일이다.

여러 하위 도메인에 걸친 시스템의 바운디드 컨텍스트에는 여러 연동 패턴이 있을 수 있다.

 

그림 4-9. 복잡한 컨텍스트 맵

 

[결론]

바운디드 컨텍스트는 서로 독립적이지 않다. 서로 상호작용해야 한다.

 

다음의 패턴은 바운디드 컨텍스트가 연동하는 다양한 방법이다.

  • 파트너십: 바운디드 컨텍스트는 애드훅 방식으로 지원한다.
  • 공유 커널: 두개 이상의 바운디드 컨텍스트가 참여하는 모든 컨텍스트를 공유하는 제한적으로 겹쳐서 공유한다.
  • 순응주의자: 사용자는 서비스 제공자의 모델을 순응한다.
  • 충돌 방지 계층: 사용자는 서비스 제공자의 모델을 사용자의 요건에 맞게 번역한다.
  • 오픈 호스트 서비스: 서비스 제공자는 사용자의 요건에 최적화된 모델인 공표된 언어를 구현한다.
  • 분리형 노선: 특정 기능을 중복으로 두는 것이 더 저렴한 경우다.