본문 바로가기

생각

DDD 와 TDD 는 함께 가야할 것 같아요.

스터디를 시작했다.

공부하고 싶었던 도메인 주도 설계 주제로 <Domain-Driven Design>를 함께 읽는다.

나는 이 책을 읽을 때 다짐했던 것이 몇 가지 있다. 

 

1. 무조건 수용하지 않을 것

2. 종합적으로 접근할 것 

3. 내가 해 온 경험과 비교하며 읽을 것

 

그래서 이 포스팅은 <Domain-Driven Design>를 읽으며 기록한 나의 잡생각에 가깝다.

책에 대한 요약서가 아니다. 

 

 

1부 동작하는 도메인 모델 만들기를 읽으면서 나는 두 가지 질문과 두 가지 깨달음을 얻었다. 

 

질문

  • 객체와 모델은 무엇이 다른가?
  • 도메인 주도 설계의 목적 중 하나인 '관련자 모두가 용어 일원화를 통해 도메인 모델에 집중하여 문제를 해결하는 것' 과 API First 는 맞닿아 있지 않을까?

 

깨달음

  • DDD 와 TDD 가 함께 병행되면 지식 탐구 과정을 궤도에 올리는 선순환고리가 만들어질 수 있다. 
  • 하찮고 작은 일이 정말 정말 정말 중요하다.  
    • 더 정확한 의미를 담을 수 있도록 메소드 이름, 변수 이름 짓기
    • 지속적인 리팩토링 
    • 사포로 마감짓듯 계속해서 모델을 디벨롭하는 것
    • 모두가 알고 인지하고 있는 이름(유비쿼터스 언어)로 소통하는 것
    • 동료와 주고 받는 용어(모델)들이 코드에도 드러나있는 것 

 

질문과 깨달음의 과정을 짧게 요약해보았다. 

글씨가 잘 안보이쥬,, 아래 포스팅에 풀어서 설명해두었습니다!

 

객체와 모델은 무엇이 다른가?

1장에서는 도메인과 모델을 정의해보았다. 모델이 '단순화하고 의식적으로 구조화된 형태'라는 점에서 객체 지향의 사실과 오해에서 읽었던 부분이 떠올랐다. '객체는 창조된다'는 것. 모델의 정의가 저러하다면 모델 역시 사실적일 필요가 없다. 모델도 해결하고자하는 도메인에 맞춰 창조된다는 말이다. 그렇다면 모델과 객체는 어떻게 다를까? 나는 모델은 설계의 관점에서, 객체는 구현의 관점에서 도메인과 연결되는 고리라고 생각했다. 도메인 모델 간의 상호작용에 관여하는 책임과 역할이 객체로 표현되는 것이지않을까? 

 

 

DDD 와 TDD 가 함께 병행되면 지식 탐구 과정을 궤도에 올리는 선순환고리가 만들어질 수 있다. 

브레인 스토밍 -> (새로운 깨달음) -> 기존 객체 변경 -> 모델도 함께 정제 -> main 코드에 변경사항 반영 

1장에서 가장 깊게 와닿았던 것은 '지식 탐구의 과정' 이라는 키워드다. 사진 왼쪽에서도 보이다시피 도메인 주도 설계를 하다보면 아래와 같은 과정을 겪는다. 근데 나는 이 과정이 어떻게 더 효율적으로 이루어질 수 있을까 하는 생각이 들었다. 내 경험상으로는 테스트가 이 과정에서 엄청난 도움을 주었다. 기존 모델이 해결하려는 도메인에 비해 비현실적이거나, 충실하게 표현할 수 없다면 새로운 모델이 필요하다. 새로운 모델이 필요하다는 사실을 깨달을 수 있게 하는 것은 기존 모델에 대한 실험이다. 그 실험의 무대가 Test 코드인 것 같다. TDD 는 DDD 를 토대로 나온 모델과 그 연결고리들이 적합한지 빠르게 실험해볼 수 있는 무대라고 생각한다. 여기에 창의성이 더해진다면 새로운 도메인 모델의 발견이 일어난다. 이걸 발전이라고 해야할까.. 발견이라고 해야할까..

 

여기에 객체 지향을 엮으면 더 잘 맞물린다. 모델 주도 설계를 통해 각 모델을 독립적으로 단위 테스트할 수 있고, 각 객체의 역할과 책임을 분리하는 객체 지향은 여기에 알맞다. 쉽게 규모를 확장하거나 결합이 쉬워서 새로운 도메인의 발견이 일어나면 맞게 끼울 수 있다. 

 

 

 

글씨가 작아서 죄송.. 다음부터는 크게 쓰겠습니다 확대하십시오..

하찮고 작은 일이 정말 정말 정말 중요하다.  

모두가 알고 인지하고 있는 이름으로 소통하는 것(유비쿼터스 언어)은 내게도 경험이 있었다. 전 회사에서 코호트 분석 프로젝트를 할 때, 관련 모델들을 정의한 뒤 기획자에게 공유했다. 우리는 그 언어를 토대로 계속 소통했다. 만약 그 과정에서 뭔가 껄끄럽고 어색한 용어라는 생각이 들면 도메인 모델의 변화가 일어나는데 여기에도 일련의 과정이 있다. 

새로운 도메인의 발견 or 기존 도메인의 변화 -> 클래스 다이어그램 수정 -> 클래스명 or 메서드 명의 변화 -> 동작 방식의 변화 -> 객체 역할과 책임의 변화 

이 과정들이 기획자와 개발자 간의 커뮤니케이션에서 반복적으로 일어나고 서로 해당 도메인에 대한 지식수준이 같아진다. 커뮤니케이션은 점점 더 원활하게되고 해결하고자 하는 문제에 집중할 수 있게 된다. 말은 쉽지 이걸 어떻게 하냐! 하는 생각이 들 수도 있을 것 같다. 나는 기획자와 개발자 간, 개발자와 개발자 간에 소통하는 언어(용어)가 코드에도 그대로 녹아들어있기만 하다면 모든 것은 수월하다! 라고 말할 수 있을 것 같다. 내가 코호트 프로젝트에서 라운드(Round) 라는 모델을 발견해냈다면, 코드에도 Round라는 객체가 존재해야한다는 말이다. 

 

기획자 : 이제보니 코호트는 기간별로 동질집단을 분리할 수 있을 것 같네요. 

나(개발자) : 그걸 라운드라고 명명하는 건 어떠신가요. 어떤 특정 기간별로 집단을 새로 묶는다는 의미에서요.

기획자 : 좋습니다!

개발자2 : 그럼 라운드 객체를 만들어야겠네요. 특정 기간에 묶인 사용자들을 담는 역할을 하겠네요. 

나(개발자) : 네 그 객체는 그런 역할이되겠네요. (지금까지는...)

 

경험상, 이 대화에서 짚고 넘어가고 싶었던 것이 '지금까지는' 이라는 말이다. 도메인 주도 설계를 하다보면 계속해서 변경된다. 테스트 코드를 기반으로 모델을 실험하고 변경하고 추가하고 제거된다. 모델 - 설계 - 구현을 계속 반복하며 정제되며 발전해나아간다. 나는 이것을 잘 모를 때 CTO 님께 계속해서 변경사항이 일어나서 버겁다고 말했다 ;  허허.. 한번에 완벽해지는 건 없어 라고 해주신 말씀이 기억에 남았다. 좀 더 자연스러워질 때까지, 계속해서 사포질하듯 다듬는 과정이 그 뒤로도 계속 수반되어야한다. CTO 님과 함께 작업할 때, 항상 변수 이름 하나에 메소드 이름 하나에 집착하시면서 시간을 쏟으셨다. 하찮다고 생각했던 일에도 정성을 기울이셨다. 껄끄러운 것들을 부드럽게 만드는 그런 과정의 반복이 개발인 것 같다. 

 

 

도메인 주도 설계의 목적 중 하나인 '관련자 모두가 용어 일원화를 통해 도메인 모델에 집중하여 문제를 해결하는 것' 과 API First 는 맞닿아 있지 않을까?

최근 API First 를 접하게되었다. 이 개념에 대한 정리글은 여기에 잘 정리되어있다. 일단 개념적으로 아주 달라보이는 둘인데, 나는 이 둘이 아주 멀리있지는 않아보였다. 도메인 주도 설계는 말 그대로 설계에 대한 이야기이고, API First 는 구현 단계에 대한 이야기라고 단정짓지 않기로했다. 모든 학문 또는 기술은 연결되어있고 나는 종합적으로 접근하려고 시도했다. 도메인 주도 설계는 동료와 소통하고 설계하고 개발하는 그 모든 단계를 도메인으로써 녹일 수 있는 기법이다. 도메인 주도 설계 안에서 API First 로 테스트가 이루어지고 프론트와 백엔드 구현이 동시에 일어날 수 있다면 ? 그러니까 높은 수준의 추상화 API 를 먼저 만들어서 프론트와 백엔드 구현을 병렬로 진행할 수 있지않을까? 하는 생각이다. 문제는 특정 도메인 모델이 어느 정도의 합의 단계에 이르렀느냐와 API First 가 얼마나 First 해야하냐다. 도메인 주도 설계의 특성상 많이 변경되는 지점인 도메인 모델을 어뎁팅 할 수 있는 정도의 인터페이스라면 얼마든지 First 해져도 상관없지않을까..? 내가 왜 이 둘을 연결지으려고 하냐면, 프론트와 백엔드 간 언어와 모델의 통일때문이다. DDD 의 D 는 도메인이고 도메인은 프로그램이 해결해야하는 문제가 존재하는 곳이다. 문제해결이라는 소프트웨어의 본질을 기반으로 설계하고 개발하는 것이 DDD 다. 프론트 개발자와 백엔드 개발자가 처음부터 끝까지 같은 문제에 집중하여 개발하는 것을 API First 가 도울 수 있지않을까 하는 생각에서다. 우리는 문제를 해결하는 사람이기 때문이다.