9.1 도메인 모델과 경계
처음 도메인 모델을 만들 때 빠지기 쉬운 함정이 도메인 모델을 완벽하게 표현하는 단일 모델을 만드는 시도를 하는 것
한 도메인은 다시 여러 하위 도메인으로 구분되기 때문에 한 개의 모델로 여러 하위 도메인을 모두 표현하려고 시도하면 오히려 모든 하위 도메인에 맞지 않는 모델을 만들게 된다.
예를 들어 상품이라는 모델을 생각해보면 카탈로그에서 상품, 재고 관리에서 상품, 주문에서 상품, 배송에서 상품은 이름만 같지만 실제로 의미하는 것이 다르다.
카탈로ㅡ에서의 상품은 상품 이미지, 상품명, 상품 가격 옵션 목록, 상세 설명과 같은 상품 정보가 위주라면, 재고 관리에서 실존하는 개별 객체를 추적하기 위한 목적으로 상품을 사용한다.
논리적으로 같은 존재처럼 보이지니만 하위 도메인에 따라 다른 용어를 사용하는 경우도 있다.
카타로그 도메인에서 상품이 검색 도메인에서는 문서로 불리기도 한다. 비슷하게 시스템을 사용하는 사람을 회원 도메인에서는 회원이라 부르지만, 주문 도메인에서는 주문자라고 부르고, 배송 도메인에서는 보내는 사람이라고 부른다.
하위 도메인마다 사용하는 용어가 다르기 때문에 올바른 도메인 모델을 개발하려면 하위 도메인마다 모델을 만들어야 한다.
모델은 특정한 컨텍스트하에서 완전한 의미를 갖는다. 같은 제품이라도 카탈로그 컨텍스트와 재고 컨텍스트에서 의미가 서로 다르다.
이렇게 구분되는 경계를 갖는 컨텍스트를 DDD에서는 바운디드 컨텍스트라고 부른다.
9.2 바운디드 컨텍스트
바운디드 컨텍스트는 모델의 경계를 결정하며 한 개의 바운디드 컨텍스트는 논리적으로 한 개의 모델을 갖는다.
이상적으로 하위 도메인과 바운디드 컨텍스트가 일대일 관계를 가지면 좋겠지만 현실은 그렇지 않을 때가 많다. 바운디드 컨텍스트는 기업의 팀 조직 구조에 따라 결졍되기도 한다.
규모가 작은 기업은 전체 시스템을 한 개 팀에서 구현할 때도 있다.
예를 들어소규모 쇼핑몰은 한 개의 웹 어플리케이션으로 온라인 쇼핑을 서비스하며 하나의 시스템에서 회원, 카탈로그, 재고, 구매, 결제와 관련된 모든 기능을 제공한다.
즉 여러 하위 도메인을 한 개의 바운디드 컨텍스트에서 구현한다.
물리적인 바운디드 컨텍스트가 한 개이더라도 내부적으로 패키지를 활용해서 논리적으로 바운디드 컨텍스트를 만든다.
여러 하위 도메인을 하나의 바운디드 컨텍스트에서 개발할 때 주의할 점은 하위 도메인의 모델이 섞이지 않도록 하는 것이다.
한 프로젝트에 각 하위 도메인의 모델이 위치하면 아무래도 전체 하위 도메인을 위한 단일 모델을 만들고 싶은 유혹에 빠지기 쉽다.
이런 유혹에 걸려들면 결과적으로 도메인 모델이 개발 하위 도메인을 제대로 반영하지 못해서 하위 도메인별로 기능을 확장하기 어렵되 된다.
→ 결론적으로 서비스 경쟁력을 떨어뜨리는 원인이 된다.
바운디드 컨텍스트는 도메인 모델을 구분하는 경계가 되기 때문에 바운디드 컨텍스트는 구현하는 하위 도메인에 알맞는 모델을 포함한다.
9.3 바운디드 컨텍스트 구현
바운디드 컨텍스트가 도메인 모델만 포함하는 것은 아니다.
바운디드 컨텍스트는 도메인 기능을 사용자에게 제공하는 데 필요한 표현 영역, 응용 서비스, 인프라스트럭처 영역을 모두 포함한다.
도메인 모델의 데이터 구조가 바뀌면 DB 테이블 스키마도 함께 변경해야 하므로 테이블도 바운디드 컨텍스트에 포함된다.
바운디드 컨텍스트는 도메인 기능을 제공하는데 필요한 모든 요소를 포함한다.
표현 영역은 인간 사용자를 위해 HTML 페이지를 생성할 수도 있고, 다른 바운디드 컨텍스트를 위해 REST API를 제공할 수 있다.
모든 바운디드 컨텍스트를 반드시 도메인 주도록 개발할 필요는 없다.
상품의 리뷰는 복잡한 도메인 로직을 갖지 않기 때문에 CRUD 방식으로 구현해도 된다.
각 바운디드 컨텍스트는 도메인에 알맞은 아키텍처를 사용한다.
서비스-DAO 구조를 사용하면 도메인 기능이 서비스에 흩어지게 되지만 도메인 기능 자체가 단순하면 서비스-DAO로 구성된 CRUD 방식으로 코드를 유지보수 하는 데 문제 되지 않는다고 생각한다.
한 바운디드 컨텍스트에서 두 방식을 혼합해서 사용할 수 있다.
대표적인 예가 CQRS(Command Query Responsibility Segregation) 패턴이다.
→ 상태를 변경하는 명령 기능과 내용을 조회하는 쿼리 기능을 위한 모델로 구분하는 패턴
각 바운디드 컨텍스트는 서로 다른 구현 기술을 사용할 수 있다.
바운디드 컨텍스트가 반드시 사용자에게 보여지는 UI를 거자고 있어여 하는 것은 아니다.
이 구조에서 UI서버는 각 바운디드 컨텍스트를 위한 파사드 역할을 수행한다.
9.4 바운디드 컨텍스트 간 통합
온라인 쇼핑 사이트에서 매출증대를 위한 카탈로그 하위 도메인에 개인화 추천 기능을 도입하기로 했다고 한다면?
기존 카탈로그 시스템을 개발하던 팀과 별도로 추천 시스템을 담당하는 팀이 새로 생겨 이 팀에서 주도적으로 추천 시스템을 만들기로 했다.
이렇게 되면 카탈로그 하위 도메인에는 기존 카탈로그를 위한 바운디드 컨텍스트와 추천 기능을 위한 바운디드 컨텍스트가 생긴다.
바운디드 컨텍스트 간 통합의 필요성
두 팀이 관련된 바운디드 컨텍스트를 개발하면 자연스럽게 두 바인디드 컨텍스트 간 통합이 발생한다.
•
사요아가 제품 상세 페이지를 볼 때 보고 있는 상품과 유사한 상품 목록을 하단에 보여준다.
사용자가 카탈로그 바운디드 컨텍스트에 추천 제품 목록을 요청하면 카탈로그 바운디드 컨텍스트는 추천 바운디드 컨텍스트로부터 추천 정보를 읽어와 추천 제품 목록을 제공한다.
카탈로그는 제품을 중심으로 도메인 모델을 구현하지만 추천은 추천 연산을 위한 모델로 구현한다.
카탈로그 시스템은 추천 시스템으로부터 추천 데이터를 받아오지만, 카탈로그 시스템에서는 추천의 도메인 모델을 사용하기보다는 카탈로그 도메인 모델을 사용해서 추천 상품을 표현해야 한다.
도메인 서비스를 구현한 클래스 인프라스트럭처 영역에 위치한다.
외부 연동을 위한 도메인 서비스 구현 클래스는 도메인 모델과 외부 시스템 간의 모델 변환을 처리한다.
RecSystemClient는 외부 추천 시스템이 제공하는 REST API를 이용해서 특정 상품을 위한 추천 상품 목록을 로딩한다.
모델간 변환이 복잡하면 별도 변환기를 둔다.
REST API를 호출하는 것은 두 바운다디 컨텍스트를 직접 통하는 방법
직접 통합하는 대신 간접적으로 통합하는 대표적인 방법은 메시지 큐를 사용하것
메시지 큐를 이용한 통합
카탈로그 바운디드 컨텍스트는 추천 시스템이 필요로 하는 사용자 활동 이력을 메세지 큐에 추가한다.
메시지 큐는 비동기로 메시지를 처리하기 때문에 카탈로그 바운디드 컨텍스트는 메시지를 큐에 추가한 뒤에 추천 바운디드 컨텍스트가 메시지를 처리할 때까지 기다리지 않고 바로 이어서 자신의 처리를 계속한다.
두 바운디드 컨텍스트를 개발하는 팀은 메시징 큐에 담을 데이터의 구조를 협의하게 되는데 그 큐를 누가 제공하느냐에 따라 데이터 구조가 결정된다.
출판/구독 모델을 이용한 바운디드 컨테스트 간 연동
큐를 추천 시스템에서 제공할 경우 큐를 통해 메시지를 추천 시스템에 전달하는 방식이 된다.
9.5 바운디드 컨텍스트 간 관계
바운디드 컨텍스트는 어떤 식으로 연결되기 때문에 두 바운디드 컨텍스트는 다양한 방식으로 관계를 맺는다.
고객/공급자 관계를 맺는 바운디드 컨텍스트
하류 컴포넌트인 카탈로그 컨텍스트는 상류 컴포넌트인 추천 컨텍스트가 제공하는 데이터와 기능에 의존한다.
카탈로그는 추천 상품을 보여주기 위해 추천 바운디드 컨텍스트가 제공하는 REST API를 호출한다.
상류 컴포넌트는 일종의 서비스 공급자 역할을 하며 하류 컴포넌트는 그 서비스를 사용하는 고객 역할을 한다.
고객과 공급자 관계에 있는 두 팀은 상호 협력이 필수적이다.
상류 컴포넌트는 보통 하류 컴포넌트가 사용할 수 있는 통신 프로토콜을 정의하고 이를 공개한다.
두 바운디드 컨텍스트가 같은 모델을 공유하는 경우도 있다. 공유하는 모델은 공유 커널이라고 부른다.
공유 커널의 장점은 중복을 줄여준다는 것이다. 두 팀이 하나의 모델을 개발해서 공유하기 때문에 두 팀에서 동일한 모델을 두 번 개발하는 중복을 줄일 수 있다.
두 팀이 밀접한 관계를 형성할 수 없다면 공유 커널을 사용할 때의 장점보다 공유 커널로 인해 개발이 지연되고 정체되는 문제가 더 커지게 된다.
마지막으로 살펴볼 관계는 독립방식으로 관계는 간단하다. 그냥 서로 통합하지 않는 방식이다.
•
두 바운디드 컨텍스트 간에 통합은 수