◆ DDD에서의 설계
▶ 유비쿼터스 언어와 도메인 모델, 바운디드 컨텍스트
● 유비쿼터스 언어는 특정 도메인의 업무 개념을 표현하는 언어
● 결제 도메인에서의 고객과 배송 도메인에서 고객은 의미가 다른데 결제 도메인에서는 구매하기 위해 상품을 결제하는 역할에서의 고객 즉 결제를 위한 신용카드 정보나 계좌 정보를 가진 결제자를 의미하고 배송 도메인에서는 구매한 상품을 배송받는 역할 즉 상품을 받을 주소와 우편번호, 전화번호를 소유한 수취자를 의미하기 때문에 이러한 개념을 고객으로 포괄적으로 표현해서는 안됨
● 명확하게 결제 서비스에서는 결제자의 개념으로 배송 서비스에서는 수취자의 개념으로 모델링해야 하는데 그래야 결제 서비스나 배송 서비스를 담당하는 팀의 의사소통이 명확해짐
● 도메인에 특화된 개념이 유비쿼터스 언어로 정의되고 이 개념들은 서로 관계를 맺는데 이 같은 관계를 표현한 모델을 도메인 모델이라 함
● 도메인 모델은 특정 비즈니스 맥락에서 통용되는 개념들의 관계를 잘 정의한 모형
● 도메인 모델을 보면 해당 비즈니스를 이해할 수 있어야 함
● 도메인 모델들을 구성하다 보면 당연히 각 도메인 모델과 다른 도메인 모델 간의 경계가 보이는데 이곳에서 사용하는 언어와 저곳에서 사용하는 언어와 개념이 상이한 이 경계가 바로 도메인의 경계 즉 바운디드 컨텍스트
● 바운디드 컨텍스트는 원으로 표현하고 원 안에 도메인 모델을 표현
● 도메인 모델은 도메인과 관련된 업무를 수행하는 제품 책임자, 도메인 전문가, 개발자를 비롯한 모든 구성원들이 업무를 이해하는 기본 모형이 됨
● 같은 컨텍스트를 다루는 이해관계자들은 도메인 모델에 정의된 언어로 업무 협의를 진행하고 개념을 발전시켜 나가고 이 모델의 언어를 그대로 사용해 설계 산출물을 표현하고 소스코드에도 사용하므로 예전처럼 설계 산출물에 사용했던 용어 와 소스코드를 구현하면서 사용하는 용어가 다른 방식을 지양
● 설계물과 코드의 용어가 상이해 해석을 위해 표준 용어 사전을 참조해야 했던 관행을 지양
● 하나의 도메인에서 사용되는 유비쿼터스 언어는 팀의 의사소통 및 실제로 동작하는 코드에서도 살아 숨 쉬어야 함
● 바운디드 컨텍스트와 유비쿼터스 언어의 관계
● 새로운 팀원이 오더라도 소스코드에 존재하는 도메인 모델을 이해하고 이 모델로 도메인 전문가와 무리없이 의사소통 할 수 있다면 도메인과 서비스에 대한 동일한 비전을 공유할 수 있고 서비스는 지속적으로 민첩하게 개발, 유지될 수 있는데 이러한 특성이 DDD와 마이크로서비스가 잘 어울리는 점
▶ 컨텍스트 매핑
● 바운디드 컨텍스트를 식별할 때 각 컨텍스트는 내부적으로는 응집성이 높고 다른 컨텍스트와 는 의존 관계가 낮아야 한다는 원칙하에 설계하는데 그렇다고 해서 컨텍스트 간에 아무런 관계가 없다는 의미는 아님
● 하나의 큰 도메인을 여러 개의 바운디드 컨텍스트로 식별하면 비즈니스 수행을 위해 여러 개의 컨텍스트가 연계해야 하는 경우가 발생하는데 이러한 컨텍스트 간의 의존 관계를 DDD에서는 컨텍스트 매핑이라 하고 연관관계에 있는 두 컨텍스트 사이에 선을 그려서 표시
● 시스템을 구성하는 컨텍스트 간의 매핑 관계를 표시한 다이어그램을 컨텍스트 맵이라고 하며 이 컨텍스트 맵을 그리려면 다양한 컨텍스트 매핑 패턴을 이해해야 함
● 주요 컨텍스트 매핑 관계
⊙ 공유 커널(Shared Kernel)
→ 공유 커널은 바운디드 컨텍스트 사이에 공통적인 모델을 공유하는 관계
→ 공유 커널은 두 개 이상의 팀에서 작지만 공통의 모델을 공유하는 관계를 나타내는데 각 팀은 공유하는 모델에 서로 합의해야 함
→ 공통 라이브러리 등이 여기에 해당하는데 이 부분이 변경되면 여러 관련 컨텍스트에 영향을 미치므로 공유하는 모델의 코드 빌드를 관리하고 테스트하는 것은 한 팀이 맡아 수행해야 함
⊙ 소비자와 공급자(Customer - Supplier)
→ 공급하는 컨텍스트는 상류(upstream)로 소비하는 컨텍스트는 하류(downstream)로 표시
→ 데이터의 흐름은 상류에서 하류로 흐르는데 반대는 가능하지 않기에 상류의 변화가 있으면 하류에서 변화를 따라야 함
→ 공급자는 소비자가 원하는 기능을 제공해야 함
⊙ 준수자(Confirmist)
→ 준수자는 소비자와 공급자와 유사하지만 상류 팀이 하류 팀의 요구를 지원하지 않거나 못하는 경우 사용
→ 이런 상황에서는 하류팀은 상류팀에서 제공하는 모델을 그대로 사용
⊙ 충돌 방지 계층(ACL - Anti-Corruption Layer)
→ 충돌 방지 계층은 하류 팀이 상류 팀의 모델에 영향을 받을 때 하류 팀의 고유 모델을 지키기 위한 번역 계층을 만드는 것
→ 이 계층은 둘 사이의 차이를 번역하며 하류 모델의 독립성을 유지
→ 상류 모델의 변경 없이 하위 모델과 통합하기 위해 데이터를 변환하는 메커니즘을 구현한 것이라 할 수 있음
→ 이러한 매핑 유형은 클라우드 기반의 마이크로서비스 아키텍처를 적용하는 새로운 시스템을 레거시 시스템과 통합하기 위해 주로 사용
→ 새로운 시스템의 특정 기능이 레거시 시스템의 기존 기능을 사용하거나 레거시 시스템의 특정 기능이 새로운 시스템의 기능을 필요로 할 수 있음
→ 예를 들어 레거시 시스템의 기존 통신 방법이 새로운 시스템이 규정한 REST API 방식을 지원하지 않을 경우 레거시 시스템이 변경될 필요가 있음
→ 이 경우 레거시를 변경할 필요없이 새로운 시스템에 충돌 방지 계층을 구현해서 레거시 시스템의 기존 연동 방식을 그대로 유지하면서 새로운 시스템과 통신하게 할 수 있음
→ 이렇게 구성한 경우 나중에 레거시 시스템이 클라우드 환경으로 이전되는 경우에도 이미 클라우드에 구축된 시스템을 변경할 필요없이 충돌 방지 계층만 없애고 서로 직접 연동하도록 호출 주소만 변경하면 됨
→ 이 같은 패턴은 레거시 시스템 전체를 마이크로서비스 환경으로 변경하는 위험을 줄이고자 하는 단계적 전환 방식에 많이 사용
→ 충돌 방지 계층을 활용한 레거시 시스템 연동
⊙ 공개 호스트 서비스(OHS - Open Host Service)
→ 공개 호스트 서비스는 바운디드 컨텍스트에 대한 접근을 제공하는 프로토콜이나 인터페이스를 정의
→ 이 프로토콜은 하류의 컨텍스트가 상위 컨텍스트에서 제공하는 기능을 용이하게 사용할 수 있도록 공개돼 있음
→ 보통 다른 컨텍스트에서 사용할 수 있는 공유된 API가 여기에 해당
⊙ 발행된 언어(PL - Published Language)
→ 발행된 언어는 하류의 컨텍스트가 상류 컨텍스트가 제공하는 기능을 사용하게 하기 위한 간단한 사용과 번역을 가능케 하는 문서화된 정보 교환 언어
→ XML이나 JSON 스키마로 표현될 수 있으며 주로 공개 호스트 서비스와 짝을 이뤄 사용
⊙ 컨텍스트 맵
→ 하나의 큰 도메인을 여러 개의 바운디드 컨텍스트로 식별하고 이들 간의 관계를 표현한 그림이 컨텍스트 맵
→ 중요도에 따른 컨텍스트 매핑 관계
→ 핵심 서브 도메인이 동작하기 위해 지원 서브 도메인과 일반 서브 도메인의 정보를 활용하고 지원 서비스 도메인 역시 동작을 위해 일반 서브 도메인을 활용한다는 것을 보여줌
→ 각 서브 도메인 간의 관계를 간단히 설명하면 일반 서브 도메인이 핵심 서브 도메인, 지원 서브 도메인과 공급자/소비자 관계를 맺고 있으며 일반 서브 도메인이 공개 호스트 서비스로 일반 서브 도메인을 사용할 수 있도록 프로토콜/인터페이스를 제공하면서 발행된 언어를 다른 컨텍스트에 제공
→ 하류의 두 컨텍스트는 충돌 방지 계층을 통해 상류 모델을 번역해서 하류에서 사용할 수 있는데 핵심 서브 도메인에 포함되는 컨텍스트는 일반 서브 도메인과 지원 서브 도메인에 속하는 컨텍스트를 사용하고 지원 서브 도메인에 포함된 컨텍스트는 일반 서브 도메인의 컨텍스트들을 사용
→ 전략적 설계로 도출된 컨텍스트를 기반으로 컨텍스트 매핑 관계를 표현한 개념적인 컨텍스트 맵은 아직 매핑을 위한 구체적인 기술 등이 정의되지 않은 상태
→ 매핑을 구현할 방안이 구체화되면 상류에서 하류 컨텍스트로 데이터를 전달하기 위해 앞에서 설명한 컨텍스트 매핑 유형들을 구체적으로 표현할 수 있음
→ 컨텍스트 맵 사례
∵ 회원, 상품, 주문, 배송의 컨텍스트 매핑 관계를 보여주며 공급자 컨텍스트들은 HTTP/JSON 기반의 REST API를 통해 동기 통신의 서비스를 제공
∵ 회원 컨텍스트는 주문 컨텍스트로 주문 컨텍스트는 배송 컨텍스트로 각각 비동기 이벤트 메시지를 발행
댓글