도메인 모델과 경계
처음 도메인 모델을 만들 때 빠지기 쉬운 함정이 도메인을 완벽하게 표현하는 단일 모델을 만드는 시도를 하는 것이다.
하지만 한 도메인은 다시 여러 하위 도메인으로 구분되기 때문에 한 개의 모델로 여러 하위 도메인을 모두 표현하려고 시도하면 오히려 모든 하위 도메인에 맞지 않은 모델을 만들게 된다.
'상품'이라는 모델을 생각해보자.
카탈로그에서의 상품.
재고 관리에서의 상품.
주문에서의 상품.
배송에서의 상품.
이름만 같지 실제로 의미하는 것이 다르다.
이렇게 하위 도메인마다 같은 용어라도 의미가 다르기 때문에 한 개의 모델로 모든 하위 도메인을 표현하려는 시도는 올바른 방법이 아니며, 표현할 수도 없다.
하위 도메인마다 사용하는 용어가 다르기 때문에 올바른 도메인 모델을 개발하려면 하위 도메인마다 모델을 만들어야 한다.
각 모델은 명시적으로 구분되는 경계를 가져서 섞이지 않도록 해야 한다.
모델은 특정한 컨텍스트(문맥) 안에서 완전한 의미를 갖는다.
같은 제품이라도 컨텍스트에 따라 의미가 다른 것처럼 말이다.
이렇게 구분되는 경계를 갖는 컨텍스트를 '바운디드 컨텍스트'(Bounded Context)라 한다.
바운디드 컨텍스트
바운디드 컨텍스트는 모델의 경계를 결정하며 한 개의 바운디드 컨텍스트는 논리적으로 한 개의 모델을 갖는다.
바운디드 컨텍스트는 용어를 기준으로 구분한다.
카탈로그 컨텍스트와 재고 컨텍스트는 서로 다른 용어를 사용하므로 이 용어를 기준으로 구분할 수 있다.
또한 바운디드 컨텍스트는 실제로 사용자에게 기능을 제공하는 물리적 시스템으로 도메인 모델은 이 바운디드 컨텍스트 안에서 도메인을
구현한다.
이상적으로 하위 도메인과 바운디드 컨텍스트가 1:1 관계를 가지면 좋겠지만.. 현실은 그럴 수 없을 때가 많다.
주문 하위 도메인이라도 주문을 처리하는 팀 & 금액 결제 처리 팀으로 따로 분리되어있다고 하면
이 경우 주문 하위 도메인에 주문 바운디드 컨텍스트와 결제 금액 계산 바운디드 컨텍스트가 존재하게 된다.
여러 하위 도메인을 하나의 바운디드 컨텍스트에서 개발할 때 주의할 점은 하위 도메인의 모델이 섞이지 않도록 하는 것이다.
한 프로젝트에 각 하위 도메인의 모델이 위치하면 아무래도 전체 하위 도메인을 위한 단일 모델을 만들고 싶은 유혹에 빠지기 쉽다.
비록 한 개의 바운디드 컨텍스트가 여러 하위 도메인을 포함하더라도 하위 도메인마다 구분되는 패키지를 갖도록 구현해야 하며,
이렇게 함으로써 하위 도메인을 위한 모델이 서로 섞이지 않고 하위 도메인마다 바운디드 컨텍스트를 갖는 효과를 낼 수 있다.
바운디드 컨텍스트 구현
바운디드 컨텍스트가 도메인 모델만 포함하는 것은 아니다.
바운디드 컨텍스트는 도메인 기능을 사용자에게 제공하는데 필요한 표현 영역, 응용 서비스, 인프라스트럭처 영역을 모두 포함한다.
모든 바운디드 컨텍스트를 반드시 도메인 주도로 개발할 필요는 없다.
예를 들어 상품의 리뷰는 복잡한 도메인 로직을 갖지 않기 때문에 CRUD 방식으로 구현해도 된다.
즉, DAO와 데이터 중심의 밸류 객체를 이용해서 리뷰 기능을 구현해도 유지 보수에 큰 문제가 없다.
한 바운디드 컨텍스트에서 두 방식을 혼합해서 사용할 수도 있다.
대표적인 예가 CQRS 패턴이다.
CQRS는 Command Query Responsibility Segregation의 약자로
상태를 변경하는 명령 기능과 내용을 조회하는 쿼리 기능을 위한 모델을 구분하는 패턴이다.
해당 패턴을 바운디드 컨텍스트에 적용하면 상태 변경과 관련된 기능은 도메인 모델 기반으로 구현하고
조회 기능은 서비스-DAO을 이용해서 구현할 수도 있다.
바운디드 컨텍스트 간 통합
온라인 쇼핑 사이트에서 카탈로그 하위 도메인에 개인화 추천 기능을 도입하기로 했다고 하자.
기존 카탈로그 시스템을 개발하던 팀과 별도로 추천 시스템을 담당하는 팀이 새로 생겨서 이 팀에서 추천 시스템을 만들기로 결정했다 해보자.
이렇게 되면 카탈로그 하위 도메인에는 기존 카탈로그를 위한 바운디드 컨텍스트와 추천 기능을 위한 바운디드 컨텍스트가 생긴다.
두 팀이 관련된 바운디드 컨텍스트를 개발하면 자연스럽게 두 바운디드 컨텍스트 간 통합이 발생한다.
이 때 카탈로그 컨텍스트와 추천 컨텍스트의 도메인 모델은 서로 다르다.
카탈로그는 제품을 중심으로 도메인 모델을 구현하지만 추천은 추천 연산을 위한 모델을 구현한다.
카탈로그 시스템은 추천 시스템으로부터 추천 데이터를 받아오지만, 카탈로그 시스템에서는 추천의 도메인 모델을 사용하기보다는
카탈로그 도메인 모델을 사용해서 추천 상품을 표현해야 한다.
그렇기에 외부 추천 시스템이 제공하는 REST API 등을 이용해서 특정 상품을 위한 추천 상품 목록을 로딩하면,
해당 데이터는 추천 시스템의 모델을 기반으로 하고 있기 때문에 API 응답은 카탈로그 도메인 모델과 일치하지 않은 데이터를 제공한다.
그렇기에 REST API로부터 데이터를 읽어와 카탈로그 도메인에 맞는 상품 모델로 변환해야 한다.
REST API를 호출하는 것은 두 바운디드 컨텍스트를 직접 통합하는 방법이다.
직접 통합하는 대신 간접적으로 통합하는 방법도 있다.
대표적인 간접 통합 방식이 메세지 큐를 사용하는 것이다.
메세지 큐는 비동기로 메세지를 처리하기 때문에 카탈로그 바운디드 컨텍스트는 메시지를 큐에 추가한 뒤에 추천 바운디드 컨텍스가
메세지를 처리할 때까지 기다리지 않고 바로 이어서 자신의 처리를 계속한다.
바운디드 컨텍스트 간 관계
두 바운디드 컨텍스트는 다양한 방식으로 관계를 맺는다.
가장 흔한 관계는 한쪽에서 API를 제공하고 다른 한쪽에서 그 API를 호출하는 관계이다.
하류 컴포넌트는 상류 컴포넌트가 제공하는 데이터와 기능에 의존한다.
상류 컴포넌트가 제공하는 API의 인터페이스가 바뀌면 하류 컴포넌트의 코드도 바뀌게 된다.
상류 컴포넌트는 일종의 서비스 공급자 역할을 하며 하류 컴포넌트는 그 서비스를 사용하는 고객 역할을 한다.
고객과 공급자 관계에 있는 두 팀은 상호 협력이 필수적이다.
공급자를 하는 상류 팀이 마음대로 API를 변경하면 하류 팀은 변경된 API에 맞추느라 우선 순위가 높은 다른 기능을 개발하지 못할 수도 있다.
반대로 상류 팀이 무언가를 변경할 때마다 하류 팀으로부터 여러 절차를 거쳐 승낙을 받아야 한다면 상류 팀은 새로운 개발에 대한 부담이 커진다.
상류 컴포넌트는 보통 하류 컴포넌트가 사용할 수 있는 통신 프로토콜을 정의하고 이를 공개한다.
상류 팀의 고객인 하류 팀이 다수 존재하면 상류 팀은 여러 하류 팀의 요구사항을 수용할 수 있는 API를 만들고 이를 서비스 형태로 공개해서 서비스의 일관성을 유지할 수 있다. 이런 서비스를 가리켜 공개 호스트 서비스라고 한다.
상류 컴포넌트의 서비스는 상류 바운디드 컨텍스트의 도메인 모델을 따른다.
그렇기에 하류 컴포넌트는 상류 서비스의 모델이 자신의 도메인 모델에 영향을 주지 않도록 보호해주는 지대가 필요하다.
변환해주는 기능이 이에 해당한다.
'책 정리 > 도메인 주도 개발 시작하기' 카테고리의 다른 글
Chapter 11. CQRS (0) | 2023.12.22 |
---|---|
Chapter 10. 이벤트 (1) | 2023.12.22 |
Chapter 8. 애그리거트 트랜잭션 관리 (0) | 2023.12.15 |
Chapter 7. 도메인 서비스 (0) | 2023.12.12 |
Chapter 6. 응용 서비스와 표현 영역 (1) | 2023.12.12 |