# 9장: 도메인 모델과 바운디드 컨텍스트

## 바운디드 컨텍스트

### 등장 배경

* 도메인은 다시 여러 하위 도메인으로 구분되기 때문에 한 개의 모델로 여러 하위 도메인을 모두 표현하려고 시도하면 오히려 모든 하위 도메인에 맞지 않는 모델을 만들게 된다.
  * 예를 들어 카탈로그에서 상품, 재고 관리에서 상품, 주문에서 상품, 배송에서 상품은 이름만 같고 실제로 의미하는 것이 다르다.
* 논리적으로 같은 존재이지만 하위 도메인에 따라 다른 용어를 사용하는 경우도 있다.
  * 예를 들어 시스템을 사용하는 사람을 회원 도메인에서는 회원이라고 부르지만, 주문 도메인에서는 주문자라고 부른다.
* 한 개의 모델로 모든 하위 도메인을 표현하는 것은 사실살 불가능하며, 하위 도메인마다 사용하는 용어도 다르므로 올바른 도메인 모델을 개발하려면 **하위 도메인마다 모델을 만들어고 각 모델이 명시적으로 구분되고 섞이지 않도록 관리해야 한다.**
* **바운디드 컨텍스트**란 이처럼 **구분되는 경계를 갖는 컨텍스트**를 의미한다.
  * 예를 들어 카탈로그 컨텍스트와 재고 컨텍스트에서 `상품`은 전혀 다른 의미를 갖게 된다.

### 개념

* 바운디드 컨텍스트는 모델의 경계를 결정하며 한 개의 바운디드 컨텍스트는 논리적으로 한 개의 모델을 갖는다.
* 바운디드 컨텍스트는 용어를 기준으로 구분한다.
* 도메인 모델은 바운디드 컨텍스트 안에서 구현된다.
*   하위 도메인과 바운디드 컨텍스트는 항상 일대일 관계가 될 수는 없다.

    * 주문 하위 도메인에 주문을 처리하는 팀과 복잡한 결제 금액 계산을 처리하는 팀이 나뉘어 있다면 하나의 하위 도메인에 두 바운디드 컨텍스트가 존재하게 된다.
    * 용어를 명확하게 구분하지 못하면 두 하위 도메인을 하나의 바운디드 컨텍스트에서 구현하기도 한다.

    <figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2Fbxd98lH0YTrf7SrU8AE7%2Fimage.png?alt=media&#x26;token=529454ba-a3d8-49a8-a4d1-90323a7e4555" alt=""><figcaption></figcaption></figure>

    * 전체 시스템을 한 개의 팀에서 구현한다면 한 개의 바운디드 컨텍스트에서 여러 하위 도메인을 구현하게 될 것이다.
    * 주의해야 할 점은, 한 개의 바운디드 컨텍스트가 여러 하위 도메인을 포함하더라도 하위 도메인마다 구분되는 패키지를 갖도록 구현해야 한다는 것이다.

    <figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2FePjYQtN5Rb5MPlcjwGHs%2Fimage.png?alt=media&#x26;token=120a647b-47da-40c7-9019-ed2349aa2464" alt=""><figcaption></figcaption></figure>

### 구현

* 바운디드 컨텍스트는 도메인 모델 뿐만 아니라 표현 영역, 응용 서비스, 인프라스트럭처 영역을 모두 포함한다. 도메인 모델의 데이터 구조가 변경되면 DB 테이블 스키마도 변경되므로 DB 테이블도 바운디드 컨텍스트에 포함된다.

<figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2F2ulQfB0Ql9eJHJp1Y5t7%2Fimage.png?alt=media&#x26;token=fa62c128-396a-4a26-9601-3d2dd7182ed9" alt="" width="188"><figcaption></figcaption></figure>

* 각 바운디드 컨텍스트는 도메인에 알맞은 아키텍처를 사용하면 된다. 복잡한 도메인 로직이 필요 없다면 단순히 CRUD 방식으로 구현해도 된다.
* 또한 바운디드 컨텍스트마다 서로 다른 구현 기술을 사용할 수도 있다.
* 한 바운디드 컨텍스트에서 여러 방식을 혼합해 사용해도 된다.
* CQRS를 적용한다고 가정했을 때 아래와 같이 상태 변경과 같은 기능은 도메인 모델 기반으로 구현하고, 조회 기능은 단순 CRUD 방식으로 구현할 수 있다.

<figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2FwXBlW08gQYmZGRXJm581%2Fimage.png?alt=media&#x26;token=2818350e-26fa-453a-a1a8-f510675ca253" alt="" width="375"><figcaption></figcaption></figure>

## 바운디드 컨텍스트 간 통합

*   **REST API를 호출**하여 두 바운디드 컨텍스트를 **직접적으로** 통합할 수 있다.

    * 예를 들어 카탈로그 바운디드 컨텍스트에서 사용자의 추천 카탈로그 조회 요청을 처리하기 위해 추천 바운디드 컨텍스트에 API를 호출하여 데이터를 가져올 수 있다.
    * 아래는 도메인 서비스를 두어 추천 도메인의 기능을 사용하면서도 카탈로그 도메인에는 영향을 주지 않도록 한 구조이다.

    <figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2Ft5RhaqVIqQUG966LArKl%2Fimage.png?alt=media&#x26;token=9a0ee04f-1bba-4bf3-874e-b22839eae155" alt=""><figcaption></figcaption></figure>
*   **메시지 큐를 사용**해 두 바운디드 컨텍스트를 **간접적으로** 통합할 수 있다.

    <figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2Fp9WK9hAorfZQqESZRvan%2Fimage.png?alt=media&#x26;token=074cf7f7-285e-4200-b120-680587d41afb" alt=""><figcaption></figcaption></figure>

    * 예를 들어 카탈로그 바운디드 컨텍스트는 추천 시스템이 필요로 하는 사용자 활동 이력을 메시지 큐에 추가할 수 있고, 추천 시스템은 이 메시지를 받아와 추천 알고리즘에 적용할 것이다.

> **마이크로서비스**
>
> 애플리케이션을 작은 서비스로 나누어 개발하는 아키텍처 스타일으로, 개별 서비스를 독립된 프로세스로 실행하고 각 서비스가 REST API나 메시징을 이용해서 통신하는 구조를 갖는다.
>
> 마이크로서비스는 각각 프로젝트를 생성하므로 바운디드 컨텍스트마다 프로젝트를 만든다고 볼 수 있고, 이를 통해 두 바운디드 컨텍스트의 모델이 섞이지 않도록 해준다.
>
> 별도 프로세스로 개발한 바운디드 컨텍스트는 독립적으로 배포하고 모니터링하며 확장되는데 이 역시 마이크로서비스가 갖는 특징이다.

## 바운디드 컨텍스트 간 관계

* 두 바운디드 컨텍스트 간 관계 중 가장 흔한 관계는 한쪽에서 API를 제공하고 다른 한쪽에서 그 API를 호출하는 관계이다.
* API를 호출하는 구독자 입장인 바운디드 컨텍스트는 공급자 바운디드 컨텍스트의 데이터와 기능에 의존한다. 공급자 바운디드 컨텍스트의 API가 변경되면 구독자 바운디드 컨텍스트의 코드도 변경되어야 한다.
* 공개 호스트 서비스란 이렇게 공급자 팀이 여러 구독자 팀의 요구사항을 수용할 수 있는 API를 만들어 서비스 형태로 공개하는 것을 의미한다.
* 공개 호스트 서비스의 대표적인 예가 검색이다. 블로그, 카페 등의 바운디드 컨텍스트는 검색 바운디드 컨텍스트에 의존하며, 공개 호스트 서비스를 사용해 검색 기능을 각자 이용하게 된다.

<figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2F4zhB3IUKabOCfqnbQlur%2Fimage.png?alt=media&#x26;token=0f143b07-ae3a-43a5-9177-a853c2250c96" alt=""><figcaption></figcaption></figure>

* 여러 바운디드 컨텍스트 간 중복 설계를 막기 위해 같은 모델을 공유할 수 있으며, 이 때 바운디드 컨텍스트 간 공유되는 모델을 **공유 커널**이라고 부른다.
  * 예를 들어 운영자를 위한 주문 관리 시스템과 고객을 위한 주문 시스템 간에 주문을 표현하는 모델을 공유해 사용할 수 있다.
* 여러 바운디드 컨텍스트를 아예 독립적으로 두는 방식도 있지만, 만약 연동해야 한다면 별도의 시스템을 두어 바운디드 컨텍스트들을 통합해야 할 것이다.

## 컨텍스트 맵

<figure><img src="https://946524419-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZqOTWctN1y9hEXEl4sKd%2Fuploads%2FX0Gp6N9g4gxhr93WdA8d%2Fimage.png?alt=media&#x26;token=37e45dd3-4ee6-49e3-9c48-8bc8c72556d5" alt=""><figcaption></figcaption></figure>

* 전체 비즈니스를 한눈에 볼 수 있고 각 바운디드 컨텍스트의 경계와 서로 어떤 관계를 맺고 있는지를 확인하는 수단이다.
* 여기서 OHS는 오픈 호스트 서비스이고, ACL은 Anti-Corruption Layer를 의미한다.
* 하위 도메인과 일치하지 않는 바운디드 컨텍스트를 찾아 도메인에 맞게 바운디드 컨텍스트를 조절하고 사업의 핵심 도메인을 위해 조직 역량을 어떤 바운디드 컨텍스트에 집중할지 파악하는 데 도움을 준다.
