이제는 비즈니스 중심의 설계를 고려해야 할 때
지은이 : 반 버논
- 도메인 주도 설계 구현, Reactive Messaging Patterns with Actor Model 저자
- www.VaguhnVernon.co
인사이트 1
사실 소프트웨어 모델링은 인간적인 일이다. (어린 시절 레고쌓기를 생각해보라)
DDD는 시각과 청각으로 움직이고 사고하는 사람들이 팀으로 모여 전략을 시각적이고 실천적으로 만드는 데 도움을 준다. 만약 프로젝트의 비즈니스가 복잡하다면 컨텍스트 맵을 그리고, 이벤트 스토밍을 통해 백앤드의 복잡도를 팀이 함께 이해하는 것이 좋은 결과를 내는 시작이 된다.
인사이트 2
많은 팀이 소프트웨어 설계의 중요성을 잊곤 한다. 대신 '작업 보드 셔플'을 주로 하는데 스크럼 제품 백로그처럼 팀 개발 작업 목록을 칸반 형태로 옮기는 수준이다. 여기에는 프로그래머가 어느정도 소스를 쏟아내야 할지 드러나지 않는다. 스크럼에서는 팀의 '지식 획득' 을 가장 중요한 원칙 중 하나로 이야기 한다.
** Essential Srcum - 지식은 결코 공짜로 얻어지지 않는다
그런데 주로 일정 관리를 위해 스크럼을 사용하는 경우
정해진 일정 내 소프트웨어 릴리즈를 마쳐야 한다는 압박감만 생겨날 뿐이다.
이 압박감은 다음의 결과를 초래한다
- 문제를 신중하게 연구, 설계하기보다는 기술적으로 해결하려 한다. 이는 최신 유행, 눈에 띄는 것만 좇게 한다.
- 데이터베이스에 너무 큰 우선순위를 무여하고, 대부분 논의가 비즈니스 보다는 DB 주변의 솔루션과 데이터 모델링에 집중된다.
- 비즈니스 목적에 따라 클래스와 오퍼레이션 이름 짓는 것에 큰 관심이 없게 만든다. 결국 비즈니스 멘탈 모델과 개발자가 만들 소프트웨어의 갭을 가져온다
- 개발과 비즈니스 사이에 협업의 고리가 약해진다. 고작 일부분만 찾아 읽는 개발 명세서에 집착하게 만든다.
- 프로젝트에 대한 예측을 너무 강하게 자주 요구하게 된다. 심사숙고한 설계보다 '작업 보드 셔플'을 추종하고 적절하게 분산된 충분한 크기의 모델이 아니라 아주 큰 진흙덩어리를 만든다
- 실제 구체적인 비즈니스 요구 대신 현재와 상상 속 미래의 요구를 모두 고려한 과도하게 일반화한 솔루션에 집착하게 만든다
- 오퍼레이션을 수행하는 서비스가 또 다른 서비스를 직접 호출하며 강하게 디펜던시를 가진다. 이 결합은 시스템 유지보수를 어렵게 만든다.
설계를 포기하고 얻은 비용감소는 결국 더 큰 비용낭비를 초래한다.
설계는 필연적이다. 좋은 설계의 대안은 나쁜 설계다. - 더글라스 마틴
인사이트 3
설계의 첫 번째는 도메인을 명확하게 바라봐야 한다는 것이다.
그래서 문제 영역과 해결 영역을 나눠야 한다.
문제 영역은 주어진 프로젝트의 제약사항 내 단계를 설계하는 곳이다. 상위수준 목표와 위험 사항을 체크하고 간단히 다이어그램을 쓸 수도 있다. 반면 해결 영역은 해결 방안을 구현하는 곳이다. 바운디드 컨텍스트 내 메인소스, 테스트소스를 생산한다.
바운디드 컨텍스트는 의미적으로 동일한 컨텍스트 범위를 말한다. 하나의 바운디드 컨텍스트 내 컴포넌트는 해당 컨텍스트에 특화되어 있다. 그리고 해당 컨텍스트 안에서만 의미가 살아난다.
따라서 바운디드 컨텍스트를 기준으로 일하는 팀을 생성하고, 언어를 공유한다. 이를 보편언어라고 부른다. 보편언어는 클래스로도 구현될 수 있다.
바운디드 컨텍스트가 조직의 핵심 전략으로 여겨진다면 이를 핵심 도메인이라 불른다. 핵심 도메인은 가장 중요한 소프트웨어 모델이며 가치 있는 것을 달성하는 수단이다. 따라서 핵심도메인에 최적의 자원을 투자해야한다.
보편언어를 사용한다는 것은 어떤 의미인가?
누군가 보편언어를 쓴다면,
팀 모두가 그 표현이 가진 제약사항과 정확한 의미를 이해한다 (PO 든 디자이너든 QA 든 모두가 아는 것이 획득된 팀의 지식이다)
보편언어를 달리하는 각 바운디드 컨텍스트끼리는 어떻게 소스를 공유하나?
각 바운디드 컨텍스트는 단일 팀이 할당된다. 그리고 독립적인 소스 코드 리파지토리가 있다. 한 팀이 다수의 바운디드 컨텍스트에 대해 일할 수 있지만, 다수의 팀이 하나의 바운디드 켄텍스트를 함께 작업할 수는 없다. 보편언어를 나눈 것처럼 해당 바운디드 컨텍스트마다 소스코드와 데이터베이스 스키마를 명확히 분리해야 한다 . 그리고 메인 소스 코드와 함께 인수테스트, 단위 테스트를 진행해야 한다.
각 팀은 각자의 소스코드와 데이터베이스를 소유하지만 공식 인터페이스를 정의하여, 바운디드 컨텍스트를 다른 팀이 사용할 수 있게 허용한다. (= 다른 팀이 메인소스 코드를 바꿨을 때 원치않는 결과를 만드는 것을 원천적으로 막을 수 있다)
인사이트 4
비즈니스의 정책은 바운디드 컨텍스트를 구분하는 중요한 기준이 된다.
만약 사업부서 A, B, C의 정책을 하나의 설계로 통합한다면, 아주 큰 진흙덩어리가 만들어질 것이다.
DDD는 각 정책을 서로 다른 바운디드 컨텍스트로 분리하라고 조언한다. 정책이 다르면 언어가 달라지고 그에 따른 기능 차이가 존재한다는 것을 인정한다.
이처럼 바운디드 컨텍스트는 아주 큰 진흙 덩어리가 아니라 명확하게 토막난 '문제를 풀기에 충분한 크기' 단위이기에 테스트할 양이 적다. 그래서 더 빠른 테스트를 수행한다는 가치가 있다.
DDD를 수행하는 개발자는 비즈니스의 핵심 전략 목표를 받아들이기로 전제되어 있어야 한다. 이는 프로그래밍 언어와 기술보다 비즈니스와 협업하여 거듭된 피드백이 만드는 화합된 멘탈모델에 더 큰 가치를 둔다는 것을 의미한다. 이를 완성하는 것은 끊임없는 대화와 탐구 그리고 현재 지식 기반의 도전과 그 결과다.
보편언어는 어떻게 개발하나?
명사일 필요는 없다. 시나리오를 생각해보자. 문서로 나오겠지만 이는 설계를 위한 도구일 뿐이다. 최종 모델설계는 결국 코드로 나온다.
ex. Given (주어진) | When (~ 할 때) | Then (그러면 ~ 할 것이다)
이 예시처럼 시나리오 명세를 활용해서 도메인 모델을 검증하는 것도 방법이다.
이렇게 시나리오로 작성된 요구사항 명세는 하나의 멘탈 모델이지만 시스템 프로스세와 닮아있다 (Command 후 Event가 발생하는데 System이 해줘야 할 것이 있을 것이며, Policy가 제한 요소로 동작하며, Event 후 Read Model이 업데이트 되며 다음 command에 영향을 준다)
바운디드 컨텍스트 안에는 무엇이 있나?
도메인 이벤트와 소통하는 인풋 어댑터
- 보안
- 사용자 인터페이스
- 표시
어플리케이션 서비스
- 보안
- 트랜젝션
- 작업 코디네이션
- 유스케이스 컨트롤러
도메인 모델
- 엔티티
- 비즈니스 로직
- 도메인 이벤트
아웃풋 어댑터
- 리파지토리
- 문서
- 캐시
- 메세징
기술은 아키텍처 전반에 산재하지만 도메인 모델은 기술로부터 최대한 자유로워야 한다. 트랜젝션은 애플리케이션 서비스에 의해 관리되는 것이지 도메인 모델에 의해 관리되는 것이 아니다.