모델 무결성 보존
Last updated
Last updated
기업 규모의 대형 프로젝트에서 통일된 하나의 큰 모델을 유지하는 것은 쉽지않다.
차라리 의도적으로 처음부터 여러 개의 모델로 분할하라
이것을 전략적 설계라고 부를 수 있다.
모델에 적용할 수 있는 컨텍스트를 정의하라
대규모 모델을 하나의 작은 것으로 분할하는 명확한 기준은 없다.
분할된 컨텍스트는 모듈이 아니다. 모듈을 포함하는 개념이다. 분할된 컨텍스트는 논리적으로 1개의 모델을 갖는다.
예를들어, 전자상거래 서비스가 있다면 domain은 전자상거래이다.
subdomain 과 Bounded Context 가 꼭 1대1은 아닐 수 있다.
분할된 컨텍스트는 유비쿼터스 언어의 일부인 고유한 이름이 있어야한다. 팀 간 의사소통이 원활해진다.
모델의 각 구성 요소들이 어떤 역할을 수행하는지 확실히 이해하기 위해 팀 내 의사소통을 해야한다. ㄴ그렇지 않으면, 순수성을 해친 코드, 단일 모델로 통합되지 않는 코드를 작성할 수 있다.
새로운 구성 요소가 기존 모델에 조화롭게 추가되고, 올바르게 구현되도록 보장할 수 있는 프로세스가 필요하다.
컨텍스트 맵은 서로 다른 분할된 컨텍스트들과 그들의 관계에 대해 개요를 표현한 문서
모든 사람은 각 컨텍스트의 범위와 코드의 맵핑 상태를 알고 있어야 한다.
컨텍스트 맵핑 기술/패턴을 통해 분할된 컨텍스트간 역할, 관계를 설명할 수 있다.
컨텍스트 간 상호작용의 수준이 높음 : 공유커널 패턴, 고객-공급자 패턴
컨텍스트 간 독립성이 높음 : 분할방식 패턴
내외부 상호작용을 다룬 패턴 : 오픈호스트서비스 패턴, 변질방지 패턴
5-3-1. 공유-커널 (Shared Kernel)
각 분할된 컨텍스트가 하나의 모델을 공유해야한다면, 명시적으로 공유된 부분으로 지정할 수 있다.
단순 모델 공유가 아니라, 코드 및 DB도 포함될 수 있다.
중복 개발을 줄여준다.
공유된 부분은 상대 팀과 의사소통을 하면서 변경해야한다.
5-3-2. 고객-공급자 (Customer-Supplier)
A와 B가 있을 때, B가 A에게 전적으로 의존을 한다면, A는 공급자이고, B는 고객이다.
고객-공급자 관계는 공유커널을 사용할 수 없을 때이다.
공유된 하나를 갖는게 맞지 않는다.
공통 코드를 기술적으로 가질 수 없는 구조다.
고객-공급자 관계는 양쪽 팀이 관계 유지에 관심이 있을 때, 성공할 수 있다.
고객은 공급자에게 요구사항을 표현하고, 공급자는 계획을 제공하며 의사소통하라.
예를들어, 전자상거래 서비스는 리포팅 서비스가 하나도 안중요하지만, 리포팅 서비스는 전자상거래의 모든 데이터를 사용한다.
컨텍스트 상호 간 인터페이스가 정교하게 정의되어야하고, 테스트케이스로 안전하게 검증되어야 한다.
이 경우가 가장 많다.
5-3-3. 순응 (Conformity)
고객-공급자 관계에서 두 팀이 관리체계(서로 다른회사거나)가 없거나, 공급자가 매우 바쁘다면, 관계를 유지할 수 없게 된다.
고객이 공급자의 모델을 사용해야 한다면 순응해야한다.
순응하지 않아도 된다면, 고객 팀은 아래의 여지가 있다.
공급자 모델을 아예 고려하지않고 분할방식 패턴으로 별도의 모델을 만들어라
공급자 모델이 사용하기 불편하다면, 변질방지레이어를 사용해라
공유 커널과 차이점은 고객이라서 공유된 부분에 변경을 가할 수 없다는 것이다.
cf) 주로 API를 일방적으로 사용하는 경우
5-3-4. 변질 방지 레이어 (Anticorruption)
DDD로 만들어진 어플리케이션은 레거시 어플리케이션이나 분리된 어플리케이션과 상호작용을 할 일이 있을 수 있다.
도메인 모델과 레거시 모델 간 일정 수준으로 통합이 필요하다
네트워크나 DB를 통해 외부 데이터를 가져올 수 있으나, 원시 데이터이다. 여기에는 모델에 대한 정보가 없고 시맨틱이 숨어있다.
변질 방지 레이어는 외부 시스템을 추상화하고 외부에는 외부언어로, 내부에는 클라이언트언어로, 양방향 번역자의 역할을 한다.
변질 방지 레이어의 변환을 통해 컨텍스트 내 순수함을 지킬 수 있다.
외부 인터페이스 변경에도 기존 도메인 모델의 영향도를 낮출 수 있다.
실제 구현은 Facade 패턴을 활용한다.
Facade : 서브시스템에 있는 인터페이스들을 통합하여 사용하기 쉽고 고수준의 인터페이스를 제공
Adapter : 클라이언트가 이해할 수 있는 것으로 변환. 두 시스템간 번역
Translator : 객체와 데이터를 번역
5-3-5. 분할 방식 (Separate Way)
한 묶음의 요구사항에서 모델링과 설계의 관점에서 공통(=의존된)된 부분이 없다면 어플리케이션을 쪼개서 개발할 수 있다.
독립적으로 개발된 모델은 다중에 다시 합치기가 매우 어려우므로, 통합이 나중에라도 필요하지 않을지 면밀히 검토해야한다.
5-3-6. 오픈 호스트 서비스 (Open Host Service)
어떤 어플리케이션에서 여러 서브시스템을 통합하려 할 때, 번역(내부와 외부의 완충지대)을 위한 레이어를 만든다.
만약, N개의 서브시스템을 통해 데이터를 얻어온다면, N개마다 번역레이어가 필요할 것이고 유사한 코드가 반복될 것이다.
오픈 호스트 서비스는 외부 서브시스템을 서비스의 제공자로 바라보는 관점으로, 외부 서브시스템을 서비스로 감싼다.
자신의 시스템에 접근할 수 있는 프로토콜(ex. http, rpc, socket)을 서비스의 집합으로 정의하고 호환프로토콜을 공개하라.
고객-공급자 패턴에서는 고객이 요청을 해야하지만, 오픈호스트서비스 패턴은 요청이 예상될만한 것들을 미리 만들어 제공하는 느낌
어떤 예외적인 서브시스템에는 일회용 번역기를 사용하라
증류 뜻 : 혼합체를 구성하고 있는 물질을 분리해 내는 절차
대규모 도메인 모델은 리팩터링을 많이 거쳐도 여전히 거대하다. 따라서, 이것은 증류가 필요하다.
핵심 도메인을 정의해야 한다. 일반적인 것으로부터 핵심 개념을 추출해야 한다.
증류로 생기는 부산물은 서브도메인이다.
핵심(core) 도메인과 서브(generic) 도메인을 분리해내는데 많은 노력을 쏟아라.
핵심 도메인을 기준으로 인력을 채용하고 최고의 개발자들을 핵심 도메인 구현에 할당하라.
개발자들은 인프라스트럭처, 최신기술에 매력을 느끼지만, 이것보다 도메인이 더욱 중요하다.
개발자 입장 ex) 비행도메인을 잘 아는게 개발자에게 뭐가 중요하겠는가? 프로젝트 끝나면 아무 의미가 없다.
도메인 비즈니스는 도메인의 심장이고 핵심 설계나 구현의 실수는 프로젝트의 실패로 귀결된다.
아무리 멋진 기술적 부가기능(인프라스트럭처, 기술스택 등)은 핵심 비즈니스가 제 역할을 하지못한다면 모두 무용지물이다.
서브도메인, 일반 모델이 분리되었다면 핵심 도메인보다 우선순위를 낮게 개발하라.
선택과 집중
서브도메인 작업에 핵심 개발자를 투입X. 도메인 관련 지식을 얻을 수 없기 때문이다.
서브도메인(ex. 검색)을 구현하는데 아래 방법들을 검토해봐라
상용 솔루션(오픈소스) : 이미 완성된 것을 사용해라. 기능부족이나 버그가 있다면 기다려야할 수도 있다.
외주 : 설계와 구현을 다른 회사에 맡기고 핵심도메인에 집중하라. 통합이 불편하고 서브도메인과 소통하기 위해 인터페이스를 정의해야한다.
기존 모델
사내(In-House) 개발 : 높은 수준의 통합을 이룰 수 있으나, 비용이 많이 든다.