NEXTSTEP에서 24/04/20~21 진행했던 '도메인 주도 설계의 사실과 오해' 수업을 들었다.

멘토했던 부트캠프의 학생들이 프로젝트 주제를 MSA로 잡았는데, 내가 MSA에 대해서 알고 있는것도 없기도 하거니와

무언가 알려주고 싶은데, MSA와 DDD는 항상 붙어다니는 사이기도 하고 옛날 김영한 강사님의 인강을 들을 때 항상

조영호 강사님의 '객체지향의 사실과 오해' 시리즈를 추천해주셔서, 어떤 생각을 가지고 계신지 궁금하기도 했다.

 

결론적으로 이틀 수업하기에 나름 비싼 가격이었지만, 짧은 시간동안 정말 많은 것을 깨달았다.

아래의 내용들은 추후 코드로 예제를 만들어 블로그에 기고할 생각이다.

 

많이 와닿았던 부분은 다음과 같다.

1. 설계에 정답은 없다.

나름 큰 충격이었던게, 마음 속으로만 아키텍쳐 설계란 대체 무엇일까? 라고 생각만 하고 있었는데, 나름 무엇인가 해답을 찾으러 간 수업에서 설계에 정답은 없다는 이야기를 들으니 새삼 충격으로 다가왔다.

 

2. DDD는 방법론, 프레임워크가 아닌 '사고방식'에 가깝다.

그러나 설계에 정답은 없다는 말이, 설명을 들으면 들을수록 점점 와닿게 되었다. DDD는 강제되거나 '그래도 이 방법이 맞다'고 하는 것이 아니라, 베스트 프랙티스를 제시해 놓고 본인이 마주하는 도메인에 따라 테일러링을 해서 사용해야 하기 때문이다.

3. 도메인이란?

'도메인이란 무엇이다'라고 확실히 정의할 수는 없지만, 정리하자면 도메인은 '현실 세계'이다. 개발자들의 직업병인지 모르지만, 은행 거래처럼 가용성과 확장성을 포기해서라도 같은 트랜잭션 안에 도메인에서 정답이라고 생각하는 플로우들을 모조리 때려박거나, 트랜잭션 일관성(Transactional Consistency : 모든 노드의 데이터를 같게 한다)이나 각 DB의 Sync를 실시간으로 맞추기 위해 정말 많은 노력을 기울인다. 그러나 현실은 그렇지 않다. 유저들은 때로는 본인이 중요하지 않다고 생각하는 것에서는 많은 주의를 기울이지 않을 수도 있고, 시장에서 물건을 거래하면서 계획에 없던 흥정을 만들어내기도 한다. DDD는 이 현실적인 도메인 문제를 도메인 전문가와 개발자가 서로 합치된 개념을 유비쿼터스 언어로 녹여 코드에 최대한 비슷하게 반영하는것에 가깝다. 마치 우리가 알고리즘을 보면서 한 문장 한 문장 중요하다고 생각하는 부분을 머릿속에 그려내 그것을 코드에 녹여내는 것처럼. 또한, 도메인은 쉴새없이 빠르게 바뀌기 때문에 애자일 스타일의 개발 방법론과 정말 잘 맞다. 

4. 불변식(Invariants)

수업을 듣고 DDD에서 가장 중요한 한 가지를 꼽으라면, 바로 '불변식'을 꼽겠다.

객체의 State와는 상관없이 만족해야 하는 도메인의 Rule이자, 객체의 State 변화는 바로 이 '불변식' 아래에서 움직여야 한다. 불변식이 중요한 이유는, 불변식에 맞춰서 Aggregate를 짜고, 트랜잭션을 묶고, 식별자로 추적해야 하는 Entity와 값만 같으면 추적할 필요가 없는 Value Object를 설계하고, 리포지토리 단위를 두어야 하기 때문이다. 이 불변식의 개념을 몰랐기 때문에 예전 프로젝트를 진행할 때 모든 엔터티에 대해 리포지토리를 만들어줬고, 어느 값 객체를 Collection으로 담아주어야 하는지 몰랐다. 

5. 애그리거트(Aggregate)

애그리게이트, 또는 애그리거트라고도 불리는 이 개념은 DDD에서 핵심이 된다. DDD도 결국엔 라이프사이클이 존재하고, 이 라이프사이클을 관리하기 위한 빌딩 블록(베스트 프랙티스)중 하나인 애그리거트는 불변식을 만족하는 최소한의 그룹이다. 따라서 불변식이 깨지지 않게 하기 위해서는 Root Aggregate를 설정하고, 이 Root Aggregate가 불변식의 만족을 담당하는 '책임'을 져야 한다. 애그리거트를 계획할 때에는 주의해야 하는 것이, 애그리거트 단위로 트랜잭션을 돌리고 그 외에는 Event로 돌려야 하기 때문에 이 애그리거트 단위로 불변식을 이행하는지를 잘 살펴야 한다.

Command와 Event의 차이는 '취소가 가능한가?'이다. Event는 이미 일어난 일을 기준으로 발행되기 때문에 취소를 할 수가 없다. 

6. 왜 DDD는 MSA / 헥사고날 아키텍쳐와 연관되는가?

결국 이 질문에 대한 답을 듣기 위해 수업을 들은 것과 마찬가지다. 아마 모놀리식 아키텍쳐에서 멀티모듈 아키텍쳐로, 그곳에서 더 진화해서 마이크로서비스 아키텍쳐로의 진화를 꾀하는 프로젝트의 가장 큰 물음은 다음과 같을 것이다:

도대체 어떤 기준으로 서비스를 찢어야 하는가?

 

그래서 때로는 Layer 단위(Service, Database, ... )로, 때로는 Vertical하게(주문, 결제 등의 서비스 위주) 나눈다. 그러나 그 원칙은 Bounded Context( 쉽게 생각하면, "니가 이 도메인을 가지고 팀을 나눈다면 어떤 팀으로 나눌 건데?"로 생각하면 쉽다.) 가 적용되는 단위가 된다. 바운디드 컨텍스트란 특정한 도메인 모델이 적용되는 범위로, 같은 바운디드 컨텍스트 안에서는 도메인 모델의 통합성을 유지하고, 서로 다른 바운디드 컨텍스트 사이에서는 통합성(Integration)을 신경쓰지 않는다.

다만, 컨텍스트 맵(Context Map)을 통해 서로 다른 바운디드 컨텍스트 사이의 관계와 모델 변환 방식을 잘 정의해놓아야 한다.

 

그래서 MSA에서는 중복을 허용한다. 중복이라는 것은, 단순히 이름이 같다고 중복이 아니라 A가 바뀔 때 B가 바뀌면 중복이라고 정의한다. 중복을 포함해서 설계란 항상 트레이드오프로 구성되어있기 때문에 이 방법을 택할 때와 저 방법을 택할 때에 항상 장단점이 존재한다. MSA로 구성하게 되면 필연적으로 코드의 전체 소스는 늘어나게 된다.

 

OOP를 동반할 때에는 중복되는 로직을 최대한 지양했는데, DDD에서는 '중복'이라는 의미가 OOP와는 다르게 적용되기 때문에 이것을 이해하는 것이 힘들어서 계속 DDD를 찾게 되는 것 같다.

+ Recent posts