Published on

2. 바운디드 컨텍스트 연동 학습과 실습

Authors
  • avatar
    Name
    이건창
    Twitter

Introduction

도메인 주도 설계는 크게 전략적 설계와 전술적 설계로 나뉜다. 그 중 전략적 설계를 이해하고 적용하는 방법에 대해 정리한다.

해당 글에서는 바운디드 컨텍스트 연동 설계를 정리한다.

전략적 설계 과제

팀 스터디를 진행하며 실습 과제로 전략적 설계 구현 과제를 만들었고 정리했다.

  • 요구사항
    • 사용자는 회원 가입 후 로그인 해 서비스를 이용할 수 있습니다.
    • 회원은 공간을 예약할 수 있습니다. 공간은 늘어날 수도 줄어들 수 있습니다.
    • 회원은 전체 공간 정보를 확인할 수 있습니다. 정보에는 방 크기, 시간 당 비용, 현재 사용 여부가 기록됩니다.
    • 회원은 특정 공간을 선택하고 하루 날짜 단위로 예약 시간을 확인할 수 있습니다.
    • 회원은 특정 공간을 제어할 수 있습니다. 전등을 키고 끌 수 있습니다.
  • 과제
    • 도메인을 분류한다.
    • 유비쿼터스 언어를 정의한다.
    • 바운디드 컨텍스트 경계 간 소통 방법 정의한다.

학습

바운디드 컨텍스트 간 연동 방법을 정리해봤다.

  • 협력형 패턴
    • 파트너십 패턴
      • 써야할 상황 : 두 팀이 효과적으로 의사소통하고 협력할 의향이 있는 경우다.
      • 특징 : 프로토콜이 임시방편으로 조정되며 모든 통합 문제는 커뮤니케이션으로 해결한다.
    • 공유 커널 페턴
      • 써야할 상황 : 모델의 일부분을 분리해서 공통(모듈)으로 관리한다.
      • 특징 : 바운디드 컨텍스트의 연동 컨트랙트를 공동 소유 저장소로 분리한다.
  • 사용자-제공자 패턴
    • 순응주의자 패턴
      • 써야할 상황 : 제공자(업스트림)에 힘이 있는 경우며 사용자 요구를 지원할 이유가 없는 경우다.
      • 특징 : 서드 파티 API를 사용하는 경우 순응주의자 패턴이 자주 보인다. 산업 표준이거나 잘 구축된 모델이면 사용자(다운스트림)의 자율성을 포기하는게 정당화된다.
    • 충돌 방지 계층(ACL)
      • 써야할 상황 : 제공자(업스트림)에 힘이 있지만 사용자(다운스트림)이 순응하지 않는 경우 사용한다. 사용자(다운스트림)는 충돌 방지 계층(ACL)을 운영하며 제공자(업스트림)에게 수정할 필요를 알린다.
      • 특징 : ACL은 다운스트림이 핵심 도메인인 경우, 업스트림이 비효율적인 경우, 업스트림이 계약을 자주 변경하는 경우 사용한다.
    • 오픈 호스트 서비스(OHS)
      • 써야할 상황 : 사용자(다운스트림)에 힘이 있지만 제공자(업스트림)는 사용자에게 최고 서비스를 제공하는 일에 관심을 가지는 경우 사용한다. 구현 모델 변경으로 사용자를 보호하기 위해 인터페이스와 구현 모델을 분리한다.
      • 특징 : OHS는 연동 지향 언어(integration-oriented language)를 사용한 퍼블릭 프로토콜을 인터페이스로 노출한다. 연동 모델을 분리하면 공표된 언어를 여러 버전으로 노출할 수 있어 사용자가 점진적으로 새로운 버전으로 이관할 수 있는 환경을 제공한다.
  • 분리형 노선 패턴
    • 써야할 상황 : 협업 의지가 없는 경우 사용한다.
    • 특징 : 두 바운디드 컨텍스트 간의 통신을 제한하고 각자의 모델을 유지한다.

협력형 그룹 패턴

협력형 그룹 패턴 컨텍스트 맵은 다음처럼 표시한다.

파트너십 패턴공유 커널 패턴
이미지이미지

사용자-제공자

사용자-제공자 패턴 컨텍스트 맵은 다음처럼 표시한다.

사용자, 제공자를 정의하고 협력 그룹과 다르게 독립적으로 성공할 수 있다. 그렇기에 컨트랙트 주도하는 불균형이 존재하므로 주의해야 한다.

사용자-제공자 패턴순응주의자 패턴
이미지이미지

ACL과 OHS 패턴은 다음처럼 표시한다.

충돌 방지 계층 패턴(ACL)오픈 호스트 서비스 패턴(OHS)
이미지이미지

사용자-제공자 패턴에 모델 변환 방법

사용자-제공자 패턴에서는 모델 변환 방법에 따라 구현 방식이 다르다.

  • 스테이트리스 변환(stateless translation)
    • 써야할 상황 : 모델을 통합하지 않아도 되는 경우 사용한다.
    • 특징 : OHS 또는 ACL 등 모델 변환을 소유하는 바운디드 컨텍스트에서 프록시 패턴을 구현해 목표하는 모델을 매핑한다.
  • 스테이트풀 변환(stateful translation)
    • 써야할 상황 : 모델 변환을 기록하거나 단일 모델로 통합하는 경우 사용한다.
    • 특징 : 여러 요청을 모아 집계한다.

스테이트리스 변환(stateless translation)은 동기 방식과 비동기 방식으로 구현할 수 있다.

  • 동기 방식
    • 써야할 상황 : 모델 변환이 코드 베이스에 포함되는 경우 사용한다.
    • 특징 : 동기 통신은 코드 베이트에 변환 로직을 포함하는 방식이다.
    • 이미지

동기 방식은 경우에 따라 변환 로직을 API 게이트웨이 패턴같은 외부 컴포넌트로 넘기는게 편리할 수 있다. 이런 API 게이트웨이를 교환 컨텍스트라고도 불린다.

  • OHS 활용한 API 게이트웨이 : 여러 버전을 관리하는 프로세스에 적합하다.
  • ACL 활용한 API 게이트웨이 : 여러 방식을 통합하는 경우 적합하다.
OHS 활용한 API 게이트웨이ACL 활용한 API 게이트웨이
이미지이미지

ACL 활용한 API 게이트웨이는 하나의 제공자가 여러 다운스트림에게 서비스를 제공할 때 도움됐다. 예시로 여러 서비스 접근을 위한 회원 권한 조회 기능을 API 게이트웨이에서 제공했고 한 곳에서 모델 변환 책임을 관리할 수 있었다.

이미지

OHS 활용한 API 게이트웨이는 모델 변환 동작에 변경이 필요할 때 도움됐던 경험이 있다. 새롭게 클라이언트 인증 로직을 추가할 때 사용자 동작을 보호해야 했고 API 게이트웨이에서 새롭게 공표된 언어를 추가했고 점진적인 이관을 도왔다.

이미지
  • 비동기 방식
    • 써야할 상황 : 관련 없는 메시지를 필터링해 노이즈를 줄여야 하는 경우 사용한다.
    • 특징 : 중개하는 컴포넌트인 메시지 프록시를 이용해 구현한다.
    • 이미지

비동기 방식은 OHS로 관리하게 된다. OHS를 채택하면 컨텍스트 구현 상세를 캡슐화 가능하다.

이미지

이벤트 주도 아키텍처에서 Private event/Public event로 구분해서 설계한다고 하는데 아직은 학습하지 않아서 모른다.

  • 업스트림 내부 이벤트는 Private event이며 도메인 이벤트다.
  • 업스트림 외부 이벤트는 Public event이며 공표된 언어다.

스테이트풀 변환(stateful translation)은 두 가지 케이스가 있다.

  • 데이터 집계 : 성능 최적화를 위해 일괄 처리가 필요한 경우 사용한다.
  • 요청 통합 : 다른 바운디드 컨텍스트 간 요청을 집계하는 경우 사용한다.

데이터 집계 변환은 정교한 스테이트 풀 처리가 필요하기에 데이터를 추적할 수 있는 영구 저장소가 필요하다. 일부 유스케이스는 상용 제품(일괄 처리 솔루션 - Spark, 스트림 처리 플랫폼 - Kafka)을 사용하는 경우도 있다.

이미지

여러 요청 통합하는 경우도 두 가지 케이스가 있다.

  • 사용자 인터페이스가 여러 서비스에서 발생하는 데이터를 결합하는 경우 (BFF 패턴)
  • 여러 컨텍스트 데이터를 처리하기 위해 복잡한 비즈니스 로직을 구현하는 경우

여러 컨텍스트 데이터를 처리하기 위해 복잡한 비즈니스 로직을 구현하는 경우는 ACL을 전면에 배치해 바운디드 컨텍스트 연동비즈니스 로직 복잡성을 분리하는 것도 방법이다.

이미지

결론

  • 바운디드 컨텍스트를 관리하는 팀 간 소통 방식을 고려해 협력형 패턴을 사용할지, 사용자-제공자 패턴을 사용할지, 분리형 노선 패턴을 사용할지 고려한다.
  • 사용자-제공자 패턴 사용시 누가 힘을 가지는지에 따라 구현 방식이 달라진다. 순응주의자 패턴, 충돌 방지 계층 패턴, 오픈 호스트 서비스 패턴을 고려한다.
  • 사용자-제공자 패턴 사용시 모델 변환 방법에 따라 구현 방식이 달라진다. 스테이트리스 변환, 스테이트풀 변환을 고려한다.

거시적 설계 관점에서 조직 문제를 파악하기 위해서 연동 패턴을 분석해 컨텍스트 맵으로 표현한다.

이미지
  • 바운디드 컨텍스트 연동은 팀 간 소통 방식, 모델 관리 책임, 모델 변환 방식으로 결정한다.

실습

커뮤니케이션 영역 선정

기능 별 의존도를 분석해 커뮤니케이션 영역을 선정했다. 기능은 다음처럼 구분했다.

  • CASE 1 : 회원은 전체 공간 리스트를 확인한다. 노출될 공간 정보는 방 크기, 시간 당 비용, 현재 대여 여부다.
  • CASE 3 : 회원은 공간을 선택해 정보를 조회한다. 해당 공간 예약 리스트, 크기를 노툴한다.
  • CASE 2 : 회원은 전체 공간 리스트에서 공간을 선택해 공간 예약한다.
  • CASE 4 : 회원은 예약한 공간전등을 제어한다.
이미지

커뮤니케이션 패턴 설계

커뮤니케이션 패턴은 다음처럼 정리했다.

  • 예약 -> 공간 : 사용자-제공자 패턴 사용했다. Rental 은 핵심 도메인으로 변경이 많이 발생한다. ACL, OHS 동작이 요구되고 업스트림 또는 다운스트림에서 제어가 필요하다.
  • 회원 -> 예약 : 공유 커널 사용 했다. 일반 도메인에서 지원하는 기능이고 변경이 적기 때문에 선택했고 회원이 모듈을 관리한다.
  • 회원 -> 공간 : 공유 커널 사용 했다. 일반 도메인에서 지원하는 기능이고 변경이 적기 때문에 선택했고 회원이 모듈을 관리한다.
  • 클라이언트 -> 공간 : 사용자-제공자 패턴 사용했다. 독립적인 작업이 요구되고 변경이 많이 발생하기에 선택했다. 그에 따라 ACL 또는 OHS 동작이 요구되고 업스트림 또는 다운스트림에서 제어가 필요하다.
이미지

방을 예약하는 경우 누가 책임을 가져야할지 고민하기도 했다.

  • 공간 도메인에서 예약 도메인을 조회한다.
  • 예약 도메인에서 공간 도메인 조회한다.
이미지

시스템 의존도를 고려했을 때 두 가지 고민이 생겼다.

  • 공간 도메인에서 예약 도메인을 조회하는 경우 : 의존성 순환 참조 가능성이 없다. 그러나 공간 정보만 관리하는 도메인과 무관한 로직이 추가된다.
  • 예약 도메인에서 공간 도메인 조회하는 경우 : 순환 참조 가능성이 존재한다.
이미지

이런 경우 요청 통합 방식 중 사용자 인터페이스가 여러 서비스에서 발생하는 데이터를 결합하는 경우 (BFF 패턴)를 고려해 쉽게 구현할 수 있다.

이미지

다음은 전체 기능을 BFF 패턴으로 구현한 케이스다.

이미지

ACL 계층을 전면에 배치한 BFF 패턴 단점 극복

여러 요청 통합하는 케이스 중 여러 다른 컨텍스트의 데이터를 처리하고 이를 위해 복잡한 비즈니스 로직을 구현해야 하는 바운디드 컨텍스트다. 이 경우 모든 바운디드 컨텍스트에서 데이터를 집계하는 충돌 방지 계층(ACL)을 바운디드 컨텍스트 전면에 배치하려 바운디드 컨텍스트 연동과 로직 복잡성을 분리할 수 있다.

  • P 154

BFF 패턴을 남발한다면 BFF 컴포넌트에 많은 책임이 몰리게 되고 결국 실행 흐름에 비즈니스 로직이 추가될 여지를 준다. 그래서 ACL 계층을 전면에 배치해 바운디드 컨텍스트 연동과 로직 복잡성을 분리하는 일을 고민했다.

단순하게 ACL 계층을 전면에 배치한다면 어떤 목적으로 설계됐는지 파악하기 어렵다. 그래서 새로운 도메인을 추가한다면 쉽게 접근할 수 있겠다고 생각했다.

처음 고민했던 권한 도메인을 활용했다.

이미지

공간을 예약하는 기능에서는 권한회원공간의 ACL 역할을 수행한다.

이미지

공간의 전등을 제어하는 기능에서는 권한회원예약의 ACL 역할을 수행한다.

이미지

권한은 BFF 패턴과 각 도메인 간 ACL 역할을 수행하며 바운디드 컨텍스트 연동과 로직 복잡성을 분리하는 역할을 맡았다.

이미지