DDD 도메인 모델과 바운디드 컨텍스트

도메인 모델과 경계

  • 하위 도메인마다 같은 용어라도 의미가 다르고 같은 대상이라도 지칭하는 용어가 다를 수 있기 때문에 한 개의 모델로 모든 하위 도메인을 표현할 수 없다.
  • 올바른 도메인 모델을 개발하려면 하위 도메인마다 모델을 만들어야 한다. 각 모델은 명시적으로 구분되는 경계를 가져서 섞이지 않도록 해야 한다.
  • 여러 하위 도메인의 모델이 섞이기 시작하면 모델의 의미가 약해질 뿐만 아니라 여러 도메인의 모델이 서로 얽히기 때문에 각 하위 도메인별로 다르게 발전하는 요구사항을 모델에 반영하기 어려워진다.
  • 모델은 특정한 컨텍스트 하에서 완전한 의미를 갖는다. 같은 제품이라도 카탈로그 컨텍스트와 재고 컨텍스트에서 의미가 서로 다르다. 이렇게 구분되는 경계를 갖는 컨텍스트를 DDD에서는 바운디드 컨텍스트라고 부른다.

바운디드 컨텍스트

  • 바운디드 컨텍스트는 모델의 경계를 결정하며 한 개의 바운디드 컨텍스트는 논리적으로 한 개의 모델을 갖는다.
  • 바운디드 컨텍스트는 실제로 사용자에게 기능을 제공하는 물리적 시스템으로 도메인 모델은 바운디드 컨텍스트 안에서 도메인을 구현한다.
  • 여러 하위 도메인을 하나의 바운디드 컨텍스트에서 개발할 때 주의할 점은 하위 도메인의 모델이 섞이지 않도록 하는 것이다.
  • 한 개의 바운디드 컨텍스트가 여러 하위 도메인을 포함하더라도 하위 도메인마다 구분되는 패키지를 갖도록 구현해야 하며, 이렇게 함으로써 하위 도메인을 위한 모델이 서로 뒤섞이지 않고 하위 도메인마다 바운디드 컨텍스트를 갖는 효과를 낼 수 있다.

  • 물리적인 바운디드 컨텍스트가 한 개이더라도 내부적으로 패키지를 활용하여 논리적으로 바운디드 컨텍스트를 만든다.
  • 바운디드 컨텍스트는 도메인 모델을 구분하는 경계가 되기 때문에 바운디드 컨텍스트는 구현하는 하위 도메인에 알맞은 모델을 포함한다. 같은 사용자라 하더라도 주문 바운디드 컨텍스트와 회원 바운디드 컨텍스트가 갖는 모델이 달라진다.

  • 회원의 Member는 애그리거트 루트이지만 주문의 Orderer는 밸류가 된다. 카탈로그의 Product는 상품이 속할 Category와 연관을 갖지만 재고의 Product는 카탈로그의 Category와 연관을 맺지 않는다.

바운디드 컨텍스트 구현

  • 바운디드 컨텍스트는 도메인 기능을 제공하는 데 필요한 표현 영역, 응용 서비스, 인프라스트럭처 영역, DB 테이블 모두 포함한다.
  • 모든 바운디드 컨텍스트를 반드시 도메인 주도로 개발할 필요는 없다. 복잡한 도메인 로직을 갖지 않는 기능은 CRUD 방식으로 구현해도 된다. 즉 DAO와 데이터 중심의 밸류 객체를 이용해서 기능을 구현해도 유지 보수하는 데 큰 문제가 없다.
  • 한 바운디드 컨텍스트에서 두 방식을 혼합해서 사용할 수 있다. CQRS 패턴을 단일 바운디드 컨텍스트에 적용하면 상태 변경과 관련된 기능은 도메인 모델 기반으로 구현하고 조회 기능은 서비스-DAO를 이용해서 구현할 수 있다.

바운디드 컨텍스트 간 통합

  • 바운디드 컨텍스트 간 통합에는 REST API를 활용하는 직접 통합 방식과 메시지 큐를 사용하는 간접 통합 방식이 있다. 비동기로 데이터를 전달하는 것을 제외하면 REST API를 사용하는 것과 차이는 없다.

마이크로서비스는 애플리케이션을 작은 서비스로 나누어 개발하는 아키텍처 스타일이다. 개별 서비스를 독립된 프로세스로 실행하고 각 서비스가 REST API나 메시징을 이용해서 통신하는 구조를 갖는다. 이런 특징은 바운디드 컨텍스트와 잘 어울린다. 각 바운디드 컨텍스트는 모델의 경계를 형성하는데 바운디드 컨텍스트를 마이크로서비스로 구현하면 자연스럽게 컨텍스트별로 모델이 분리된다. 코드로 생각하면 마이크로서비스마다 프로젝트를 생성하므로 바운디드 컨텍스트마다 프로젝트를 만들게 된다.

바운디드 컨텍스트 간 관계

  • 두 바운디드 컨텍스트 간 관계 중 가장 흔한 관계는 REST API가 대표적이다. 이 관계에서 API를 사용하는 바운디드 컨텍스트(하류 컴포넌트)는 API를 제공하는 바운디드 컨텍스트(상류 컴포넌트)에 의존하게 된다.

공개 호스트 서비스(OPEN HOST SERVICE)

  • 상류 컴포넌트는 보통 하류 컴포넌트가 사용할 수 있는 통신 프로토콜을 정의하고 이를 공개한다. 예를 들어 추천 시스템은 하류 컴포넌트가 사용할 수 있는 REST API를 제공하거나 프로토콜 버퍼와 같은 것을 이용해서 서비스를 제공할 수도 있다. 상류 팀의 고객인 하류 팀이 다수 존재하면 상류 팀은 여러 하류 팀의 요구사항을 수용할 수 있는 API를 만들고 이를 서비스 형태로 공개해서 서비스의 일관성을 유지할 수 있다. 이런 서비스를 공개 호스트 서비스 라고 한다.
  • 공개 호스트 서비스의 대표적인 예가 검색이다. 검색을 위한 전용 시스템을 구축하고 검색 시스템과 각 서비스를 통합한다. 이 때 검색 시스템은 상류 컴포넌트가 되고 블로그, 카페, 게시판은 하류 컴포넌트가 된다. 상류 팀은 각 하류 컴포넌트의 요구사항을 수용하는 단일 API를 만들어 공개하고 하류 팀은 공개된 API를 사용해서 검색 기능을 구현한다.

공유 커널(SHARED KERNEL)

  • 두 바운디드 컨텍스트가 같은 모델을 공유하는 경우. 예를 들어 운영자를 위한 주문 관리 개발 팀, 고객을 위한 주문 서비스 개발 팀에서 주문을 표현하는 모델을 공유함으로써 주문과 관련된 중복 설계를 막을 수 있다. 이렇게 두 팀이 공유하는 모델을 공유 커널이라고 부른다.
  • 공유 커널은 중복을 줄여준다. 하지만 두 팀이 한 모델을 공유하기 때문에 한 팀에서 임의로 모델을 변경하면 안 되며 두 팀이 밀접한 관계를 유지해야 한다.

독립 방식(SEPARATE WAY)

  • 두 바운디드 컨텍스트 간에 서로 통합하지 않고 독립적으로 모델을 발전시키는 방식
  • 독립 방식에서 두 바운디드 컨텍스트 간의 통합은 수동으로 이루어진다. 예를 들어 온라인 쇼핑몰 솔루션과 외부의 ERP 서비스를 사용하고 있다고 하자. 온라인 쇼핑몰 솔루션은 외부 ERP 서비스와의 연동을 지원하지 않으므로 온라인 쇼핑몰에서 판매가 발생하면 쇼핑몰 운영자는 판매정보를 보고 ERP 시스템에 입력해야 한다.
  • 수동 통합 방식에는 한계가 있으므로 두 바운디드 컨텍스트를 통합해주는 별도의 시스템을 만들어야 할 수도 있다.

컨텍스트 맵

  • 바운디드 컨텍스트 간의 관계를 표시한 지도.
  • 시스템의 전체 구조를 보여준다.
  • 그리는 규칙은 따로 없다. 간단한 도형과 선을 이용해서 각 컨텍스트 관계를 이해할 수 있는 수준에서 그리면 된다.
Reference
  • 도메인 주도 개발 시작하기, 최범균 지음

Categories:

Updated:

Comments