처음 도메인 모델을 만들 때 빠지기 쉬운 함정이 도메인을 완벽하게 표현하는 단일 모델을 만드는 시도를 하는 것.
이러다 보면 오히려 모든 하위 도메인에 맞지 않는 모델을 만들게 된다.
예) 회원이라는 도메인은 다른 도메인에서는 서로 다른 의미와 다른 용어로 불리운다.
하위 도메인 마다 사용하는 용어가 다르기 때문에 올바른 도메인 모델을 개발하려면 하위 도메인 마다 모델을 만들어야 한다.
각 모델은 명시적으로 구분되는 경계를 가져서 섞이지 않도록 해야 한다. 여러 하위 도메인의 모델이 서로 얽히기 때문에 각 하위 도메인 별로 다르게 발전하는 요구사항을 모델에 반영 하기 어려워 진다.
모델은 특정한 컨텍스트(문백) 하에서 완전한 의미를 갖는다. 같은 제품이라도 카탈로그 컨텍스트와 재고 컨텍스트에서 의미가 서로 다르다.
이렇게 구분되는 경계를 갖는 컨텍스트를 DDD에서는 바운디드 컨텍스트(Bounded Context)라고 부른다.
바운디드 컨텍스트
바운디드 컨텍스트는 모델의 경계를 결정하며 한걔의 바운디드 컨텍스트는 논리적으로 한 개의 모델을 갖는다. 또한 바운디드 컨텍스트는 실제로 사용자에게 기능을 제공하는 물리적 시스템으로 도메인 모델은 이 바운디드 컨텍스트 안에서 도메인을 구현한다.
이상적으로 하위 도메인과 바운디드 컨텍스트가 일대일 관계를 가지면 좋겠지만 현실은 그렇지 않을 때가 많다. 바운디드 컨텍스트는 기업의 팀 조직 구조에 따라 결정 되기도 한다. 하지만 규모가 작은 기업은 시스템을 한 개 팀에서 구현할 때도 있다.
여러 하위 도메인을 하나의 바운디드 컨텍스트에서 개발할 때 주의할 점은 하위 도메인의 모델이 섞이지 않도록 하는 것이다. 한 프로젝트에 각 하위 모메인의 모델이 위치하면 아무래도 전체 하위 도메인을 위한 단일 모델을 만들고 싶은 유혹에 빠지기 쉽다. 이런 유혹에 걸려들면 결과적으로 도메인 모델이 개별 하위 도메인을 제대로 반영하지 못해서 하위 도메인 별로 기능을 확장하기 어렵게 되고 이는 서비스 경쟁력을 떨어뜨리는 원인이 된다.
같은 회원 데이터라 할지라도 각 바운디드 컨텍스트에 맞는 하위 도메인으로 분리 해서 관리 해야 한다.
바운디드 컨텍스트 구현
각 바운디드 컨텍스트는 도메인에 맞는 알맞은 아키텍처를 사용한다. 항상 같은 아키텍처로 구성 할 필요는 없다.
한 바운디드 컨텍스트에서 두 방식을 혼합해서 사용 할 수도 있다. 대표적인 예가 CQRS 패턴이다.
또한 각 바운디드 컨텍스트는 서로 다른 구현 기술을 사용할 수도 있다. 웹 MVC는 스프링 MVC를 사용하고 JPA를 사용하는 바운디드 컨텍스트가 존재 할 수도 있고, Netty를 이용해서 REST API를 제공하고 마이바티스를 리포지터리 구현 기술로 사용하는 바운디드 컨텍스트가 존재 할 수도 있다.
바운디드 컨텍스트 간 통합
서비스에 기능이 추가 되게 되면 기존에 존재하는 도메인에 추가 기능이 도입되게 될 수 있다. 예를 들어 카탈로그 하위 도메인에 개인화 추천 기능을 도입하기로 했다고 하자. 기존 카탈로그 시스템을 개발하던 팀과 별도로 추천 시스템을 담당하는 팀이 새로 생겨서 이팀에서 주도적으로 추천 시스템을 만들기로 했다. 두 팀이 관련된 바운디드 컨텍스트를 개발하면 자연스럽게 두 바운디드 컨텍스트 간 통합이 발생한다.
카탈로그와 추천 바운디드 컨텍스트 간 통합이 필요한 기능은 다음과 같다.
'사용자가 제품 상세 페이지를 볼 때, 보고 있는 상품과 유사한 상품 목록을 하단에 보여준다.'
추천 시스템에서는 추천 도메인을 사용하지만, 카탈로그 시스템에서는 추천의 도메인 모델을 사용하기 보다는 카탈로그 도메인 모델을 사용해서 추천 상품을 표현해야 한다. 즉 카탈로그 모델을 기반으로 하는 도메인 서비스를 이용해서 상품 추천 기능을 표현해야 한다.
이때 외부 시스템과의 연동을 처리하고 외부 시스템과의 모델과 현재 도메인 모델간에 변환을 통해 처리하게 된다.
REST API를 호출 하는 것은 두 바운디드 컨텍스트를 직접 통합하는 방식인데, 메시지 큐를 사용하게 되면 자연스럽게 간접적으로 통합하게 된다.
바운디드 컨텍스트간 관계
여기서 카탈로그 바운디드 컨텍스트는 외부 시스템인 추천 바운디드 컨텍스트의 데이터를 가져 와서 사용하는 입장으로, 일종의 고객/공급자 관계가 형성되게 된다.
고객의 입장에서의 카탈로그 바운디드 컨텍스트는 추천 바운디드 컨텍스트에 의존성이 높아져 공급자의 변경에 민감해 질 수 밖에 없게 되고, 반대로 추천 바운디드 컨텍스트는 무언가 변경이 필요 할때 마다 고객에게 여러 절차를 걸쳐 승낙이 필요해 진다면 개선이 필요한 상황에서도 시도하기가 어려워 지게 된다.
이런 문제를 해결 하기 위해서는 공급자의 컨텍스트 도메인 모델이 자신의 도메인 모델에 영향을 주지 않도록 보호해 주는 완충 지대를 만들어야 한다. 이런 역할을 하는 계층을 안티코럽션 계층(AntiCorruption Layer)라고 한다.
두 바운디드 컨텍스트가 같은 모델을 공유하는 경우도 있다. 예를 들어 두 팀이 주문을 표현하는 모델을 공유함으로써 중복 설계를 막고자 하는 경우 인데, 이렇게 두팀이 공유하는 모델을 공유 커널(Shared Kernel)이라고 부른다.
하지만 두 팀이 한 모델을 공유하기 때문에 한 팀에서 임의로 모델을 변경하면 안 되며 두팀이 밀접한 관계를 유지해야 한다. 두 팀이 밀접한 관계를 형성할 수 없다면 공유 커널을 사용할 때의 장점보다 공유 커널로 인해 개발이 지연되고 정체되는 문제가 더 커지게 된다.
컨텍스트 맵
개별 바운디드 컨텍스트에 매몰되면 전체를 보지 못할 때가 있다. 나무만 보고 숲을 보지 못하는 상황을 방지하려면 전체 비즈니스를 조망할 수 있는 지도가 필요하다. 그것이 바로 컨텍스트 맵이다.
컨텍스트 맵은 시스템은 시스템의 전체 구조를 보여준다. 이는 사업의 핵심 도메인을 위해 조직 역량을 어떤 바운디드 컨텍스트에 집중할지 파악하는 데 도움을 준다. 컨텍스트 맵을 그리는 규칙은 따로 없다. 편한 도구를 이용해서 그리면 된다.
'리팩토링&디자인패턴' 카테고리의 다른 글
행복한 프로그래밍 > 다리 건너기 (0) | 2021.07.28 |
---|---|
프로그래밍 초식:사소한 개선 -for문 분리 (최범균님 youtube 참고) (0) | 2021.07.10 |
댓글