일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- mongo
- kakao
- armeria
- webframework
- MSA
- spring scheduler
- Pay
- springcloud
- IDDD
- 애그리거트
- 신입
- 바운디드컨텍스트
- 반버논
- springboot
- docker
- ddd
- 개발자
- Kotlin
- spring-web
- ifkakao
- springboot3
- spring6
- spring caching
- java17
- Conference
- MongoDB
- Spring
- 값객체
- Redis
- zuul
- Today
- Total
Easy Understanding
(2) DDD의 도메인과 바운디드 컨텍스트 - 개발보다는 설계부터! 본문
도메인과 바운디드 컨텍스트는 무엇이길래
이전 글에서도 이야기 했지만, DDD는 용어부터가 우리가 알고있는 것과 다르고, 익숙해져야 할 것들이 많다.
특히나 바운디드 컨텍스트(Bounded Context)에 대해서는 초반에 감이 잘 오지 않았던 것 같다.
시작전에 간단하게 요약을 해보자면,
DDD는 전략적(Strategic) 설계와 전술적(Tactical) 설계로 나뉜다.
- 전략적 설계: 개념적으로 도메인과 바운디드 컨텍스트를 정의하고, 유비쿼터스 용어를 정리하는 부분
- 전술적 설계: 세부 아키텍처와 코드의 구현과 관련된 부분
이라고 보면 되는데,
이 글에서 다루는 것이 전략적 설계의 핵심적인 부분이라고 보면 된다.
조금씩 다르지만 대략적으로 아래의 순서로 전략적 설계가 진행된다고 보면 된다.
1. 도메인/서브도메인을 정의하기
2. 바운디드 컨텍스트를 나누기
3. 유비쿼터스 언어를 결정하기
4. 컨텍스트 맵 그리기
확실한 건 이 부분은 개발적인 부분보다도, 순수하게 비즈니스적인 비중이 더 많기 때문에,
개발자만 참여하는 것이 아닌, 개발자와 실무(보통 기획자) 담당의 협업이 필요한 부분이다.
도메인과 서브도메인을 나누기
도메인 주도 설계에서 도메인은 그 크기에 따라서 두 가지 종류로 나눌 수 있다.
- 도메인
그냥 도메인이다. 도메인은 우리가 풀고자 하는 서비스의 가장 넓은 주제이다. 그냥 '카카오톡' 처럼 서비스 자체를 도메인이라고 봐도 된다. 그런데 어떤 서비스는 도메인이라고 부르기엔 너무나도 크기 때문에, 상대적인 개념이라고 보면 될 것 같다.
- 서브 도메인
서브 도메인은 도메인을 하위 개념으로 크게크게 나눈 것이다. 보통 서브도메인은 팀 이름을 갖다 붙이면 얼추 맞는다.
예를 들어,
웹툰 컨텐츠 회사라면 플랫폼 자체인 '웹툰 서비스'가 도메인이 될 수가 있다.
이제 그 하위 조직들이 대략적으로 서브 도메인이 된다.
백엔드만 기준으로 했을 때,
'회원', '컨텐츠', '마케팅', '결제', '작가관리', '광고' 같은 것들이 서브 도메인이 될 수가 있을 것 같다.
그러나 최근 큰 서비스들을 보면 이렇게 구분하기엔 너무 방대하다.
위를 기준으로 각 서브 도메인 자체도 어떻게 보면 하나의 도메인이라고 불릴 만큼 충분히 크기 때문이다.
'컨텐츠' 도메인을 예로 들면 내부적으로 '컨텐츠 제공', '컨텐츠 관리', '컨텐츠 통계' 같이 나눌 수도 있을 것이고,
이를 보조해주는 '컨텐츠 외부 연동' 같은 서브도메인도 있을 수 있다.
아마 실제로는 이것보다 더 많은 일들을 갖고 있을 가능성이 크다.
일단은 도메인과 서브도메인을 나누는 것부터 시작이다.
아직까지는 어려운 것은 별로 없어 보인다.
바운디드 컨텍스트 이해하기
언제 개발 이야기가 나오나 싶겠지만, 아직까지는 개발자의 시선이 개입될 상황은 아니다.
한 사이클의 '전략적 설계'를 거치지 않는다면, 사실상 DDD의 의미는 절반을 잃게 된다.
바운디드(Bounded)는 "경계화 된" 의 뜻을 가지는데,
단어의 뜻처럼, '컨텍스트(Context, 맥락)'이 '경계(Boundary)'를 이루고 나눠져 있다는 것이다.
적절하게 선을 그음으로서 도메인을 적절하게 나누겠다는 것이다.
그 필요성에 대해서는 다음의 예시를 확인해 보자.
게임 구매 예시
예를 들어 어떤 게임에서 '실물 재화로 아이템을 사는 경우'를 가정해보자.
이 과정에서는 보통 두 파트로 나뉘게 될 것이다.
한 부분은 '게임 개발' 파트이고,
다른 한 부분은 '결제 개발' 파트이다.
아마 게임 내부에서 아이템 구입 행위가 일어난다면,
'게임 개발'에서는 아이템의 구매적인 측면을 중심적으로 생각할 것이다.
이 아이템이 어떤 것인지, 어떤 가치를 가지고 어떻게 다루어져야 하는지에 대해서 인지하고 있을 것이다.
또한 구매가 이루어졌을 때, 인벤토리로 꽂아주는 등을 고려해야 한다.
반면, '결제 개발'에서는 이 아이템이 무엇인지, 그리고 게임 내적으로 어떤 데이터들을 다뤄야 하는지에 대해서는 전문성이 없다.
오히려 결제가 전반적으로 문제없이 진행되는지, 실제 결제 벤더사들과의 문제가 없는지에 더 초점을 맞출 것이다.
이렇게 두 개발팀에서는 같은 데이터에 대해서 해석이 다르다.
아마 내부적으로 각 팀에서 사용하는 용어도 많이들 다를 것이다.
게임 쪽은 게임 도메인에서 사용하는 용어가 익숙할 것이고, 결제는 그렇지 않을 것이다.
두 팀이 아이템 구매에 대해서 같은 RDB 테이블을 사용한다고 하면, 각자 필요한 Column을 추가해야 할 것이다.
또는 힘이 쎈 팀이 DB에 대해서 주도권을 가져갈 수도 있고...
이렇게 같은 데이터와 행위에 대해서 각 팀마다, 도메인마다 다루는 방식이 다루기 때문에,
이런 맥락이 충분하게 구분되어야 한다.
이런 맥락(Context)을 나누는 것이 바로 '바운디드 컨텍스트'다.
각 팀에서 필요한 데이터들은 그 모양과 처리 방법이 다르기 때문에, 이걸 아예 나눠버리겠다는 것이다.
게임팀에서는 게임에 관련된 데이터를 따로 관리하고,
결제팀에서는 결제에 관련된 데이터를 따로 관리한다.
데이터 저장의 흐름에 대해서는 팀끼리 조율하며, 서로의 데이터를 자신에게 맞도록 하기 위해 변환을 하기도 한다.
유비쿼터스 언어
여기에서 '유비쿼터스 언어(Ubiquitous Language)'라는 개념이 나오는데(옛날에 IT에서 유행했던 그 단어),
그냥 쉽게 말하면 각 팀에서 사용하는 실제의 비즈니스 용어다.
바운디드 컨텍스트를 나누는 과정에서는, 이 유비쿼터스 언어도 정해야 한다.
각 팀에서 사용하는 용어를 일치시키는 과정이다.
게임 팀에서 사용되는 구매와, 결제 팀에서 사용되는 구매가 아예 사용되는 단어가 다를 수가 있다.
게임에서는 '아이템 구매'
결제에서는 '상품 구매'
라고 읽고 싶을 수가 있는 것이며, 이런 것들을 다 각자의 도메인에 맞게 정하겠다는 것이다.
또한 유비쿼터스 언어에서 결정해야하는 것은 각 컨텍스트간의 용어 분리뿐이 아니다.
사실 각 팀의 개발자와 도메인 전문가(기획자)의 용어의 괴리도 상당한 편이다.
개발자들은 개발 용어로 설명하는 것을 편하게 생각하기 때문에,
그리고 도메인보다는 프로그래밍적으로(아키텍처나 코드 측면) 생각하기 때문에 문제가 생긴다.
이런 것들도 유비쿼터스 언어를 정하는 과정에서 꼭 맞춰야 한다.
컨텍스트 맵
마지막으로 이렇게 만들어진 바운디드 컨텍스트간의 관계를 정리해줄 일이 남았다.
이때 그리는 다이어그램을 '컨텍스트 맵(Context Map)'이라고 한다.
각 바운디드 컨텍스트 사이에는 어떠한 일반적인 관계의 흐름이라는 패턴이 있을 것이고,
그런 흐름이나 관계들을 표시해주면 컨텍스트 맵이 완성된다.
DDD에서는 이런 관계들에 대해서 몇 가지 용어들(ACL, OHS, PL) 같은 것들이 있지만 여기에서는 생략한다.
아마도 컨텍스트 맵에 대해서 명확한 형식에 대한 기준은 없는 것 같다.
컨텍스트들을 명확하게 나누고, 흐름과 방식에 대해서 정리하는 것이 핵심이다.
이제 개발을 시작할 수 있다
여기까지 정리가 되면 슬슬 개발을 준비할 수가 있게 된다.
이제 슬슬 DB를 설계할 수 있지 않을까?
물론 뒤의 Entity, Value Object, Aggregates를 알아야 더 명확해 지겠지만, 이제부턴 가능할 것 같다.
각 바운디드 컨텍스트에서 정해진 유비쿼터스 언어에 맞춰서 DB를 모델링하면 된다.
그렇다면 각 바운디드 컨텍스트의 DB들은 테이블로 나누는가, 아니면 논리적으로만 나누는가, 물리적으로 나누는가?
이에 대해서 사실 DDD에서는 명확하게 해답을 주지 않는다.
DDD는 전략적 패턴(위의 과정)에 대해서는 타협을 하지 않지만,
DDD의 전술적 패턴(기술적인 구현)에 대해서는 그다지 강력한 주장을 하고 있지 않다.
몇 가지 원칙만 지키되, 필요한 아키텍처를 잘 사용하면 문제가 될 것은 없다고 하는 것 같다.
그러므로 이젠 다양한 전술적 패턴을 학습하며 어떻게 개발할지 고민해볼 일만 남았다.
DDD의 전략적 패턴을 보면서 드는 생각
전략적 패턴을 공부하면서 드는 생각이 두 가지 정도가 있다.
1. 이거 생각보다 아키텍처가 복잡해지겠는데?
위의 게임 예시를 봐도 알겠지만, 바운디드 컨텍스트를 나누게 되면 같은 구입 데이터가 두 개가 된다.
만약 RDB를 사용한다면, 두 팀에서 각자 DB에 데이터를 저장하게 되는데,
이때 트랜잭션은 어떻게 처리할 지가 고민이 될 것 같다.
심지어 실제로 물리 DB까지 나눴다면 어떻게 할지 고민이 된다.
또한 DB의 양도 두 배가 되는 셈이니, 더 복잡해진 것은 확실하다.
DDD는 물론 장점이 많지만, 기술적으로 기존보다 더 복잡해질 여지가 많은 설계방식이다.
이런 기술적인 토대가 적고 부담스럽다면 DDD의 도입에 대해서는 충분히 고민을 해봐야 한다.
2. 이거 완전 MSA 아님?
바운디드 컨텍스트가 분리된 그림을 보면 아무리 봐도 MSA 구조와 비슷하다.
바운디드 컨텍스트를 만들면 자연스럽게 MSA에 대한 고민도 해결이 된다.
어차피 MSA로 나눌 거라면, 이왕 더 협업과 개발에 도움이 되는 DDD를 도입하는 게 낫지 않을까 하는 생각이다.
사실 DDD는 MSA가 유행하는 시대에 나온 이론은 아니지만,
지금은 충분히 빛을 낼 수 있을 것이라고 생각한다.
'Study' 카테고리의 다른 글
(4) DDD의 서비스/팩토리/패키지 - 코드를 작성하는 세부 방법들 (0) | 2022.03.02 |
---|---|
(3) DDD의 엔터티/값객체/애그리거트/리파지토리 - 코드에서 객체 정의하기 (1) | 2022.02.20 |
(1) DDD란 무엇인가 - 데이터 중심 개발과 도메인 중심 개발 (3) | 2022.02.06 |
Spring Security 뼈대 정리(Tomcat에서 Spring 까지의 처리 과정) (0) | 2021.07.12 |
Spring Web MVC 코드 분석(Initialization와 DispatcherServlet) (0) | 2021.06.22 |