DDD 도메인 주도 설계 9장

DDD - 도메인 주도 설계

DDD

앞으로 적어갈 글은 최범균님의 저서 DDD START!를 읽고 요약 - 정리한 글입니다.

제 9장 : 도메인 모델과 BOUNDED CONTEXT

제 9장 도메인 모델과 BOUNDED CONTEXT

도메인 모델과 경계

  • 처음 도메인 모델을 만들 때 빠지기 쉬운 함정은 도메인을 완벽하게 표현하는 단일 모델을 만드는 시도를 하는 것이다.

  • 한 도메인은 다시 여러 도메인으로 구분된다.

    • 하나의 모델로 여러 하위 도메인을 표현하려고 하면 모든 하위 도메인에 맞지 않는 모델을 만들게 된다.
  • 상품이라는 모델이 있다고 가정하자.

    • 카탈로그에서의 상품
    • 재고 관리에서의 상품
    • 주문에서의 상품
    • 배송에서의 상품
  • 위의 상품들은 이름만 같지 실제 의미하는 것이 다르다.

스크린샷 2020-11-11 오후 9 57 48

  • 반대로 시스템을 사용하는 사람을 회원 도메인에서는 회원이라 부르지만 주문 도메인에서는 주문자라고 부르며, 배송 도메인에서는 보내는 사람이라고 부른다.

  • 논리적으로 같은 존재처럼 보이지만 하위 도메인에 따라 다른 용어를 사용하는 경우도 있다.

  • 하위 도메인 마다 같은 용어라도 의미가 다르며, 같은 대상이라도 지칭하는 용어가 다를 수 있으므로 하나의 모델로 모든 하위 도메인을 표현하는 시도는 올바른 방법도 아니며 불가능하다.

  • 모델은 특정한 컨텍스트하에서 비로소 완전한 의미를 갖는다.

  • 같은 제품이라도 카탈로그 컨텍스트와 재고 컨텍스트에서 의미가 서로 다르다.

  • 이렇게 구분되는 경계를 갖는 컨텍스트를 DDD에서는 BOUNDED CONTEXT라고 부른다.

BOUNDED CONTEXT

  • BOUNDED CONTEXT는 모델의 경계를 결정하며 한 개의 BOUNDED CONTEXT는 논리적으로 한 개의 모델을 갖는다.

  • BOUNDED CONTEXT는 용어를 기준으로 구분한다.

  • 이상적으로는 하위 도메인과 BOUNDED CONTEXT가 1:1 관계를 갖으면 좋겠지만 현실은 그렇지가 않다.

  • BOUNDED CONTEXT는 기업의 팀 구조에 따라 결정되기도 한다.

스크린샷 2020-11-11 오후 10 00 59

  • 큰 기업에서는 하나의 도메인 안에 두 하위 도메인을 두 BOUNDED CONTEXT로 나눠서 개발한다.

  • 작은 기업에서는 두 하위 도메인을 하나의 BOUNDED CONTEXT에서 구현하기도 한다.

스크린샷 2020-11-11 오후 10 04 18

  • 만약 온라인 쇼핑이라는 BOUNDED CONTEXT에서 여러 개의 하위 도메인들을 BOUNDED CONTEXT로 나눌 때는 패키지를 활용해서 BOUNDED CONTEXT를 만들도록 한다.

  • 이처럼 BOUNDED CONTEXT를 나누지 않으면 하위 도메인 모델이 서로 뒤섞여서 결과적으로는 도메인별 기능 확장이 어려워지게 된다.

스크린샷 2020-11-11 오후 10 04 33

BOUNDED CONTEXT의 구현

스크린샷 2020-11-11 오후 10 05 10

  • BOUNDED CONTEXT가 항상 도메인 모델만 포함하는 것은 아니다.

  • 도메인 기능을 사용자에게 제공하기 위한 표현, 응용 서비스, 도메인, 인프라스트럭처 모두를 포함한다.

스크린샷 2020-11-11 오후 10 06 39

  • 모든 BOUNDED CONTEXT를 도메인 주도로 개발할 필요는 없다.
    • 가령 상품의 리뷰처럼 간단한 도메인 로직이라면 CRUD 방식으로 구현해도 상관이 없다.

BOUNDED CONTEXT 간 통합

  • 카탈로그 하위 도메인에 개인화 추천 기능을 도입하기로 결정했다고 가정해보자.

  • 기존 카탈로그 시스템을 개발하던 팀과 별도로 추천 시스템을 담당하는 팀이 새로 생겨서 이 팀에서 주도적으로 추천 시스템을 만든다면?

  • 카탈로그 하위 도메인에는 기존 카탈로그를 위한 BOUNDED CONTEXT와 추천 기능을 위한 BOUNDED CONTEXT가 생기게 된다.

스크린샷 2020-11-11 오후 10 08 51

  • 두 팀이 관련된 BOUNDED CONTEXT를 개발하면 자연스럽게 통합이 발생한다.

  • 카탈로그 시스템은 추천 시스템으로부터 추천 데이터를 받아오기는 하지만, 카탈로그 시스템에서는 추천의 도메인 모델이 아닌 카탈로그 도메인 모델을 사용해서 추천 상품을 표현해야한다.

스크린샷 2020-11-11 오후 10 09 50

  • 그러면 카탈로그 시스템에서는 추천 시스템으로 API 요청을 보내 데이터를 받아오게 될 텐데, 이 데이터는 카탈로그 도메인에 맞지 않을 것이므로 변환 작업이 필요하다.

스크린샷 2020-11-11 오후 10 12 27

  • 만약 두 모델 간의 변환 작업이 복잡하다면 변환 처리를 위한 별도 클래스를 만들고 이 클래스에서 변환을 처리해도 된다.

  • HTTP는 두 BOUNDED CONTEXT를 직접 통합하는 방법이다.

스크린샷 2020-11-11 오후 10 13 23

  • 직접 통합 대신 간접 통합을 하려면 어떻게 해야할까? 그런 경우라면 메시지 큐를 사용할 수 있다.

마이크로 서비스와 BOUNDED CONTEXT

여기까지 보면 BOUNDED CONTEXT를 나누는 것은 어찌보면 MSA와도 유사해보인다.

MSA의 특징은 BOUNDED CONTEXT와 매우 잘 어울린다.

BOUNDED CONTEXT는 독립적으로 배포하고 모니털이하고 확장하게 되는데 이는 MSA의 특징이기도 하다.

BOUNDED CONTEXT 간 관계

  • BOUNDED CONTEXT는 어떤 식으로 연결된다.

  • 두 BOUNDED CONTEXT 간 관계 중 가장 흔한 관계는 한쪽에서 API를 제공하고 다른 한쪽에서 그 API를 호출하는 관계다.

  • 이때 API를 사용하는 BOUNDED CONTEXT는 API를 제공하는 BOUNDED CONTEXT에 의존하게 된다.

스크린샷 2020-11-11 오후 10 18 26

  • 여기서 카탈로그는 downstream 컴포넌트이며 추천은 upstream 컴포넌트가 된다.

  • 상류 컴포넌트가 하류 컴포넌트에서 사용할 수 있는 통신 프로토콜을 정의하고 이를 공개한다. 이를 공개 호스트 서비스라고 부른다.

스크린샷 2020-11-11 오후 10 21 05

  • 가장 대표적인 예가 바로 검색이다.

  • 이러한 서비스들은 API를 통해 통신하는데 만약 RestTemplate과 같은 HTTP 클라이언트를 사용했다면 이 RestTemplate이 외부 시스템이 내 도메인 모델을 침범하지 않도록 막아주는 Anticorruption Layer가 된다.

  • 공유 커널이라고 해서 두 팀이 하나의 모델을 공유함으로써 중복 개발을 막을 수 있는 모델이 존재한다.

  • 장점은 중복을 줄여주는 것이오 단점은 두 팀이 밀접하게 협업하지 않으면 모델이 깨지므로 개발이 지연되는 문제가 발생할 수 있다는 점이다.

  • 마지막으로는 SEPARATE WAY, 독립 방식 관계가 존재한다.

스크린샷 2020-11-11 오후 10 24 30

  • 위는 극단적인 SEPARATE WAY의 예시이다.

  • 수동으로 하는 방식이 나쁜것은 아니지만 규모가 커질수록 수동 통합에는 한계가 존재하기 마련이다.

스크린샷 2020-11-11 오후 10 25 10

  • 그래서 일반적으로는 두 독립적인 BOUNDED CONTEXT를 통합하기 위해 중간 다리를 놓기도 한다.

컨텍스트 맵

  • 개별 BOUNDED CONTEXT에 매몰되어서 전체를 못보게 되는 경우가 종종 있다.

  • 나무가 아닌 숲을 보기 위해 전체 비즈니스를 조망할 수 있는 지도가 바로 컨텍스트 맵이다.

  • 컨텍스트 맵을 그리는 규칙은 없다. 화이트보드, PPT, Whatever it is!

  • 컨텍스트 맵은 시스템의 전체 구조를 보여준다.

  • BOUNDED CONTEXT를 조절하고 사업의 핵심 도메인을 위해 조직 역량을 어떤 BOUNDED CONTEXT에 집중할지 파악하는데 도움이 된다.

스크린샷 2020-11-11 오후 10 27 46

Reference

DDD START! - 최범균님 -



© 2022. by minkuk

Powered by minkuk