도메인 주도 설계(Domain Driven Design) - 1. DDD를 시작하며
It-chain의 알파버전을 2월 24일까지 개발을 마무리하고 잠시 팀원들과 휴식기를 가지기로 결정했습니다. 2달동안 열심히 개발에 참여해준 팀원들에 감사합니다.
It-chain이 아닌 갑자기 DDD(도메인 주도 설계)로 주제가 바뀐 이유는 잠깐의 휴식기 동안 It-chain에 DDD를 적용하여 리팩토링을 하기 위함입니다. It-chain의 코드의 양이 많아지고 복잡해지면서 설계가 점점 올바른 방향으로 가지 못하고 있다는 느낌이 들었고 DDD를 통해 이를 해결하는 과정 또한 의미있는 작업이라 생각하기에 DDD 시리즈 포스팅을 시작합니다.
참고한 책은 ‘‘도메인 주도 설계 구현’‘이며 책의 내용 포스팅 + it-chain에 DDD의 적용 과정 및 결과를 포스팅 할 예정입니다.
소프트웨어의 복잡성은 도메인에서 기인하고, 그러한 복잡성을 어떻게 다루느냐가 프로젝트의 성패를 좌우한다. -Eric evans
도메인 주도 설계란
도메인 주도 설계(DDD)라고 불리는 소프트웨어 개발 접근법은 우리가 높은 품질의 소프트웨어 모델을 설계할 수 있도록 해준다. DDD는 전략적인 동시에 전술적인 모델링 도구로서 중요한 비지니스 목적을 달성시킬 수 있는 양질의 소프트웨어를 설계하게 한다. DDD의 가장 중심에 있는 원리는 토의, 경청, 이해, 발견, 그리고 비즈니스의 가치, 모든 지식을 중앙화하는 모든 것이다.
DDD가 해줄 수 있는 일
-
DDD는 도메인 전문가와 소프트웨어 개발자가 비즈니스 전문가의 심적 모델을 반영한 소프트웨어를 함께 개발할 수 있게 해준다. 유비쿼터스 언어(팀의 모든 사람들에 의해 개발되며, 충분히 이해되고 있고 동일하게 사용되는 언어)를 통해 소프트웨어 개발자를 포함한 모든 팀원에게 깊은 도메인 통찰을 전파한다.
-
DDD는 비즈니스의 전략적 이니셔티브를 다룬다. DDD는 팀 내에서 조직적 관계의 정의를 돕고 소프트웨어뿐 아니라 프로젝트 전체의 실패를 야기하는 관계가 존재하는지까지도 찾아내 초기 단계에서 경고해주기도 한다.
-
DDD는 실행 가능한 소프트웨어 상품을 분석하고 개발하는 전술적 설계 모델링 도구를 사용해 실제 소프트웨어의 기술적 요구에 응한다.
DDD를 사용하는데서 오는 비즈니스 가치
-
조직이 그 도메인에 유용한 모델을 얻는다.
-
정교하교 정확하게 비즈니스를 정의하고 이해한다.
-
도메인 전문가가 소프트웨어 설계에 기여한다.
-
사용자 경험이 개선된다.
-
순수한 모델 주변에 명확한 경계가 생긴다.
-
엔터프라이즈 아키텍처의 구성이 좋아진다.
-
애자일하고, 반복적이고, 지속적인 모델링이 사용된다.
-
전략적인 동시에 전술적인 새로운 도구가 적용된다.
이번 포스팅에서는 도메인 주도 설계와 도메인 주도 설계에서 중요한 유비쿼터스 언어에 대해서 알아보았습니다. 다음에는 도메인, 서브도메인, 바운디드 컨텍스트에 대해서 알아볼 예정입니다!
도메인 주도 설계(Domain Driven Design) - 2. 바운디드 컨텍스트 및 보편언어(유비쿼터스 언어)
바운디드 컨텍스트
DDD는 주로 명확하게 바운디드 컨텍스트 내에서 보편 언어를 모델링 하는 것에 대한 것이다. 바운디드 컨텍스트는 의미적으로 동일한 컨텍스트의 범위를 표현한다. 이것은 그 범주 내에서 소프트웨어 모델의 각 컴포넌트는 특정한 의미를 갖고, 특정한 일을 수행한다는 의미이다. 바운디드 컨텍스트 내에 존재하는 컴포넌트들은 컨텍스트에 특화돼 있으며, 컨텍스트 안에서 의미가 살아난다. 바운디드 컨텍스트는 모델이 구현되는 곳이고, 바운디드 컨텍스트마다 각각 분리된 소프트웨어 산출물이 나온다. 각각의 바운디드 컨텍스트는 단일 팀에만 할당돼야 하고, 각 바운디드 컨텍스트마다 독립적인 소스 코드 리파지토리가 있어야 한다.
바운디드 컨텍스트를 사용하는 중요한 이유 중 한가지를 이해하기 위해 소프트웨어 설계에서 흔히 일어날 수 있는 문제를 생각해보자. 각 팀들은 각자의 도메인 모델을 작고 관리할 수 있는 정도에서 시작했다해도 점점 더 많은 개념이 쌓이는 것을 언제 멈춰야 하는지 모를 때가 자주 있을 것이다. 하지만 각 팀들은 더 많은 개념을 계속 추가한다. 이는 나중에 커다란 문제로 발전한다. 하나의 거대하고, 혼란스럽고, 경계가 제한되지 않은 모델 안에 너무 많은 개념이 존재하는 것은 물론, 실제로 다수의 언어가 혼재되면서 점차 모델 내의 언어가 모호해지기 시작한다.
DDD는 서로의 다른 개념들을 각기 다른 바운디드 컨텍스트 안으로 분리해 놓음으로써 개념 간 차이를 더욱 중시하고 전략적 핵심이 되는 모든 개념들을 밀접하게 유지하고 나머지는 모두 제외시킨다. 각 팀들은 자신의 바운디드 컨텍스트에만 집중하여 개발할 수 있도록 한다.
유비쿼터스 언어
유비쿼터스 언어는 팀 내에 공유된 언어다. 그것은 도메인 전문가와 개발자 간에 같이 공유된다. 그리고 실제론 해당 프로젝트에 참여하는 모든 사람 간에 공유된다. 팀에서 당신의 역할이 무엇이든, 단순히 이 프로젝트에 참여하고 있다는 이유만으로 이 유비쿼터스 언어를 사용하게 된다. 개발자들에게 사용하도록 강요되는 많은 비즈니스 용어가 아니며 도메인 전문가, 개발자, 비즈니스 분석가, 시스템을 제작하는 데 관계된 모든 사람 등과 같은 팀 전체에 의해 만들어진 실제 언어다.
- 유비쿼터스는 ‘만연하다’ 혹은 ‘어디서나 발견된다’는 의미. 즉 팀원 간에 상요되고 팀이 개발하는 하나의 도메인 모델로 발현된다는 의미다.
- 바운디드 컨텍스트당 하나의 유비쿼터스 언어가 있다.
- 바운디드 컨텍스트는 우리가 처음 상상했던 것 보다 상대적으로 더 작다. 바운디드 컨텍스트는 격리된 비지니스 도메인의 완전한 유비쿼터스 언어를 포착할 만큼만 크다.
- 유비쿼터스 언어는 바운디드 컨텍스트를 격리시키고 그 안에서 프로젝트의 개발 업부를 수행하는 팀 내부에서만 유비쿼터스하다.
유비쿼터스 언어는 팀원내에서 발생하는 커뮤니케이션의 오류를 최소화하여 프로젝트 진행을 매끄럽게하고 용어와 코드의 정보를 유지한다.
예시)
Routing 서비스에 출발지, 도착시간을 이력하면 화물이 멈춰야 할 지점을 찾고 데이터베이스에 저장한다. (모호하고 기술적임) ->
Routing 서비스는 Route Specification을 만족하는 Itenrary를 찾는다.
출처: http://opennote46.tistory.com/193 [욱’S 노트]
도메인 주도 설계(Domain Driven Design) - 3. 바운디드 컨텍스트 및 보편언어(유비쿼터스 언어)를 It-chain에 적용하기
2장에서 배운 바운디드 컨텍스트와 보편언어를 It-chain에 적용해 보았다. It-chain이라는 도메인을 여러 서브도메인으로 나누고 각각의 서브 도메인을 바운디드 컨텍스트로 정의하였다.
It-chain은 7개의 서브 도메인으로 분할하였으며 각각의 역할은 다음과 같다.
서브 도메인 | 기능 |
---|---|
Peer | 네트워크에 참여한 Peer식별 및 관리 |
Consensus | 합의 알고리즘 수행 |
SmartContract | SmartContract실행 |
Authentication | Peer인증 |
TxPool | Transaction임시 저장 및 전달 기능 |
Blockchain | 블록체인 관리 및 블록 저장 |
Communication | Peer들간의 Messaging 기능 |
7개의 바운디드 컨텍스트 중 Consensus를 대상으로 DDD의 전술적 설계를 적용해보았다.
Consensus 컨텍스트
PBFT Consensus Context
PBFT Consensus Context는 오로지 합의와 관련된 작업만을 수행한다.
요구사항(Ubiquitous Language로 작성)
- 합의(consensus)는 동시에 여러개가 진행 될 수 있다.
- ElectionPolicy에 의해 합의(consensus)에 참여할 대표(representative)가 결정된다.ElectionPolicy에 의해 선출된 대표(Repersentative)의 구성원이 혼자일 경우 합의를 바로 Confirm(확인)하고 Block완성 Event를 발생.
- 의회(Parliament)는 무조건 하나의 Leader와 0개 이상의 Member로 구성된다.
- 합의(Consensus)는 합의(Consensus)의 대상인 Block과 합의에 참여하는 대표(representative)들로 구성된다.
- Leader(리더)에 의해 시작된 합의는 IdleState, PreprepareState, prepareState, commitState, EndState단계를 거쳐 종료된다. Leader(리더)가 Block을 생성할 권리가 있는지 검사한 후 존재할 경우 합의(Consensus)를 시작한다.
- 합의(consensus)가 시작되면 합의할 Block을 포함한 PreprepareMsg를 합의에 참여하는 대표(representative)들에게 전송하고, IdleState에서 Prepreparestate로 preprepare단계를 시작(start)한다.
- PreprepareMsg를 받을 경우 Representative가 올바르게 구성되어 있는지 Parliament가 확인(Validate)한다. PreprepareMsg는 Leader가 아닌 Member들이 consensus가 시작되었다는 메세지이므로, PreprepareMsg로 부터 얻은 Consensus를 저장하고 대표(representative)들에게 prepareMsg를 전송한다. 그리고 Consensus는 preprepare단계를 시작한다.(start)한다.
- PrepareMsg를 받은 경우 MsgPool에 저장한 후(저장할 때 PrepareMsg를 보낸 Member의 ID의 중복 메세지를 검사(Check)한다.) PrepareMsg 합의 정책(PrepareMsg Consensus Policy)과 Consensus State에 의해 다음 단계로의 전환이 통과될 경우 합의에 참여하는 대표(representative)들에게 commitMsg를 전송한다. Consensus는 commitState를 시작한다.
- CommitMsg를 받은 경우 MsgPool에 저장한 후(저장할 때 CommitMsg를 보낸 Member의 ID의 중복 메세지를 검사(Check)한다.) CommitMsg 합의 정책(CommitMsg Consensus Policy)과 Consensus State에 의해 통과될 경우 합의를 종료(End)하고 합의의 대상인 Block완성 Event를 발생시키고 Consensus를 종료한다.
- Msg는 PreprepareMsg, PrepareMsg, CommitMsg 3개로 구성된다.
- 합의(Consensus)는 Leader에 의해서만 시작(start)되며 ElectionPolicy에 의해 의회(Parliament)에서 대표들(representatives)을 선출하고 합의(Consensus)에 참여할 대표들(representatives)와 Block으로 구성된다. 합의는 시작되고 특정 시간(T)이 지나면 자동으로 제거 되어야 한다. 합의가 시작되면 합의는 Prepare상태로 시작된다.
- PreprepareMsg를 받으면 해당 메세지의 Consensus를 구성하는 대표들(representatives)을 검사한다. 대표들이 이상이 없으면 합의(Consensus)를 시작하고 PrepareMsg를 전파한다.
위의 유비쿼터스 언어를 기반으로한 도메인 모델 설계 결과는 다음과 같다.
이번 포스팅에서는 유비쿼터스 언어, 바운디드 컨텍스트에 대해서 알아보았고 실제로 It-chain에 적용한 결과에대해서 알아 보았습니다. 다음포스팅에서는 위의 적용 결과를 기반으로 실제 코드로 어떻게 작성되는지를 살펴보겠습니다.