본격적인 개발을 위한 준비 - 서비스 스펙 정의하기

Updated:

지난 포스트(도메인 주도 설계에서의 전략적 설계)를 통해 도메인과 서브도메인, 바운디드 컨텍스트와 유비쿼터스 언어, 그리고 이벤트 스토밍 워크샵을 통해 마이크로서비스 식별에 대해 알아보았다. 도메인 주도 설계에서의 전략적 설계

실제 조그만 온라인 쇼핑몰을 구축하기 위한 설계를 진행해보면서 지난번 포스트를 통해 이해한 개념을 명확히 이해하고, 실제 구현을 위해 마이크로서비스의 스펙이 어떻게 정의되는지 알아보자.

쇼핑몰 이벤트 스토밍 워크샵

Domain Event 찾기

이벤트 스토밍은 이전 차시에 간단히 설명 드렸던 바와 같이 도메인의 이벤트를 찾는 것으로부터 시작한다. 이 도메인 이벤트를 찾을 때에는 시스템에서 발생하는 가장 중요한 이벤트를 찾는 것에 집중을 해야 한다. 즉, 데이터나 데이터의 구조를 어떻게 찾고 구상할 것인지가 아닌 쇼핑몰 서비스의 비즈니스 프로세스에 최우선적으로 초점을 둬야 한다는 것이다.

이렇게 해서 도메인 이벤트를 찾으면 오렌지색 스티커에 찾은 도메인 이벤트의 이름을 적는데, 이 도메인 이벤트의 이름은 과거시제의 동사 형태로 작성한다.

예를 들면 account registered, account changed 그리고 purchase requested같이 작성한다. 팀에 모두가 참여해서 찾은 도메인 이벤트는 모델링 공간의 왼쪽에서 오른쪽으로 시간의 순서대로 붙인다. 왼쪽에서 오른쪽으로 도메인 이벤트를 찾아 붙이다가 종종 몇 개의 도메인 이벤트는 다른 도메인 이벤트와 동시에 발생하는 경우도 생기게 되는데, 이런 경우에는 동시에 발생하는 도메인 이벤트를 같은 시점에 발생하는 도메인 이벤트의 아래쪽에 붙인다.

Domain Event 찾기

팀 전체가 도메인 이벤트를 찾아 시간의 흐름에 맞게 붙여나감으로써 시스템이 어떻게 동작하는지에 대해 정확히 알 수 있게 된다.

External System 찾기

이렇게 도메인 이벤트를 찾는 중에 한 단계 또는 여러 단계의 실행 프로세스를 호출하는 경우 그리고 어떤 경우는 외부 시스템과의 연결을 통해 진행되는 경우도 있는데, 이런 경우 프로세스 또는 외부 시스템의 이름을 연보라색 스티커에 적어서 이 프로세스나 외부 시스템을 발생시키는, 즉 호출하는 도메인 이벤트 스티커 근처에 붙이고, 도메인 이벤트에서 화살표로 표시를 해서 특정 이벤트가 호출하고 있음을 표시한다.

External System 찾기

Command 찾기

command는 도메인 이벤트를 발생시키는, 즉 도메인 이벤트를 동작하게 하는 명령으로 이 command의 이름은 change account, request shipment와 같이 명령어의 형태로 작성한다. 찾은 command의 이름은 파란색 스티커에 작성을 해서 이 command과 연관된 도메인 이벤트의 왼쪽에 붙인다

Command 찾기

Hot Spot 찾기

이렇게 워크샵을 진행하다보면 참여자 간 궁금한 점이나 의견의 조정이 필요한 경우가 많이 발생하게 된다. 예를 들면 ‘구매할 때 어떤 정보들이 필요하지?’, ‘신용카드 결제 프로세스를 연계하기 위해서는 더 많은 정보들이 필요한 건 아닌가?’라는 의문사항이 생길 수 있습니다. 또한 신용카드 결제가 거부되면 문자 메시지, 이메일, 화면의 팝업과 같이 사용자에게 알려주는 방법이 필요한데, ‘우리 서비스는 어떤 방법을 사용하는 것이 좋을까’라는 의사결정이 필요한 부분도 생기게 된다. 또한 ‘특정 도메인 이벤트는 더 많은 도메인에 대한 탐구와 이해를 통해서 더 구체적으로 서술되어야 하지 않을까?’라는 의견과 이를 해결하기 위한 논의가 필요한 경우도 있다.

그런데 이런 것들이 금방 정리가 되지 않는 경우도 많이 발생하는데, 이런 논의에 많은 시간을 사용하는 대신 눈에 잘 띄는 자주색 스티커에 이런 문제에 대한 내용을 작성해서 논의가 되고 있는 곳에 붙여 모두가 이 영역에 해결해야 할 문제가 있다는 것을 알 수 있게 하고, 추후 문제가 해결되면 이 자주색 스티커는 제거한다.

Hot Spot 찾기

Actor/Roll 찾기

이렇게 도출된 command는 사용자, 즉 사람 또는 사람이 아닌 특정한 역할을 통해 command가 동작하게 되는데, 이 단계에서는 사용자, 역할을 찾는다. 사용자 또는 역할을 찾을 때에는 해당 command를 동작하게 하는 구체적인 사용자나 역할을 찾는 것이 중요하다. 이렇게 찾은 사용자 또는 역할은 노란색의 작은 스티커에 이름을 적어 command 스티커의 왼쪽 아래에 약간 겹치게 붙인다. 이 사용자 역할 스티커를 해당 command에 겹치게 붙이는 것은 이 사용자 또는 역할이 이 command를 동작하게 한다는 것을 명시적으로 표현하는 것이다.

Actor/Roll 찾기

Entity/Aggregate 찾기

이런 command와 도메인 이벤트의 짝을 살펴보면, 이 이벤트의 수행 결과를 표현하는 entity aggregate을 생각해볼 수 있다. 이 entity라는 것은 이벤트 수행 결과를 표현하는 데이터, 저장하는 데이터라고 설명할 수 있다.

사실 이벤트 스토밍 워크샵을 만든 알베르토 브란돌리니는 ‘데이터라고 설명하면 안된다’라고 얘기하고 있다. 미리 데이터를 고민하게 되면 업무의 흐름과 맥락을 고려한 구분에 좋지 않은 영향을 줄 수 있기 때문이라고 합니다. 그러나 여기서 데이터라고 설명하는 이유는 결국 데이터로 이어지기 때문이다.

다시 본론으로 돌아와서, 이 entity aggregate 이름은 노란색 스티커에 작성해서 command과 도메인 이벤트 짝의 위쪽에 살짝 겹치도록 붙인다. 이렇게 command, 도메인 이벤트에서 entity aggregate을 찾는 동안 새로운 도메인 이벤트를 발견할 수 있는데, 이런 경우도 발견하는 즉시 모델링 공간 내의 흐름에 맞는 위치에 작성해서 붙인다. 주의 할 사항은 entity aggregate을 정할 때에는 여러 개념을 두루 포함하는 모호한 표현의 사용을 지양하고, command와 도메인 이벤트를 통해 수행된 결과를 명확히 표현하는 작은 범위의 구체적인 명사형의 단어를 찾는 것이 중요하다는 것이다.

Entity/Aggregate 찾기

Bounded Context, Microservice  찾기

앞에서 식별했던 Entity/Aggregate으로 식별한 단어들을 보면 의미상 그룹으로 묶을 수 있는 단어들이 보인다. 동일한 단어들을 묶거나 단어는 다른지만 의미상 비슷한 것들을 하나의 그룹으로 묶을 수 있는데, 이 묶음을 의미와 맥락의 경계로 볼수 있다. 그래서 이 묶음을 바운디드 컨텍스트라고 하며, 이 바운디드 컨텍스트가 마이크로서비스의 후보가 되며, 컨텍스트간 Dependency나 Transaction, MSA 적용 효과, 운영 효율성, 그리고 비용 등을 고려해서 최종 마이크로서비스를 도출한다.

Bounded Context 찾기

Policy 찾기

이렇게 마이크로서비스를 식별하게 되면 이벤트가 다른 컨텍스트에 영향을 주게 되는 경우가 있는데 이런 경우 아래 그림과 같이 Policy 스티커를 붙이고 화살표고 영향을 주는 컨텍스트를 표시한다.

Microservice 찾기

Service Mapping Diagram 그리기

마이크로서비스를 찾은 후에는 비즈니스 수행을 위해 서비스간의 연계가 필요하게 되는데, 이 연관관계를 찾아 서비스간 매핑 관계를 정의한다. 연관관계는 실시간의 데이터가 반드시 필요한 경우는 동기방식으로 정의하고, 그 외 데이터의 정합성을 맞춰야 하는 경우 등 마이크로서비스의 독립성을 최대한 보장하기 위해서 비동기 방식으로 정의한다. 보통 동기방식은 실선으로, 비동기 방식을 점선으로 표시한다.

Service Mapping Diagram 그리기

Service Specification 정의하기

이렇게 마이크로서비스를 식별하고, 서비스 간의 연관관계를 정의한 후에는 본격적인 상세 설계와 구현을 위해 서비스의 스펙을 정의해야 하는데, 이벤트 스토밍 워크샵 결과와 서비스 매핑의 결과를 바탕으로 각 마이크로서비스의 스펙을 정의한다. 이 서비스 스팩은 서비스를 담당하는 팀에 할당되서 상세 설계와 구현이 진행되게 된다.

Service Specification 정의하기

본격적인 Sprint로 들아가 Domain Modeling과 Coding하기

상세 설계는 도메인 모델 패턴을 기반으로 도메인 모델링을 하게 되고, 이 모델을 바탕으로 코드로 구현을 한다. 도메인 모델에서 정의한 객체는 코드의 클래스로 구현되고 객체의 속성들은 크래스의 멤버변수로 구현된다. 즉 설계가 구현으로 자연스럽게 이어질 수 있다는 것이다. 그렇게 때문에 이벤트 스토밍 워크샵 때 부터 용어를 정의할때 유비쿼터스 언어로, 명확하고 구체적인 표현으로 정의하는 것이 중요하다는 것이다.

Domain Modeling과 Coding하기

정리

과거 100% 수준의 설계를 위해 수개월의 시간을 분석/설계에 할애했었다. 명확히 분석하고 설계를 했다고는 하지만 막상 구현에 들어가게 되면 조금씩 문제가 있는 부분이 발견되기 마련이다. 그리고 개발이 끝나고 개발 결과와 설계 내용을 비교해보면 처음 설계 내용 중 2~30%에서 변경이나 삭제가 발생하고 또 새로운 설계가 추가가 되곤 한다. 이 얘기가 설계가 잘 못 되었다는 것이 아니다. 구현을 하다보면 설계단계 때 보다 더 많은 이해와 지식이 쌓이기 때문에 발생되는 당연한 현상이라고 생각한다. 심지어는 고객의 요구사항이 변경되거나 새로운 기능의 추가가 요구되기도 한다.

그렇다면 최종 7~80%의 정확돌를 갖는 100% 수준을 목표로 한 수개월의 설계 대신, 처음부터 7~80% 수준을 목표로 설계기간을 단축하는 것이 어떨까 하는 생각을 해볼 수 있다. 이것을 실현하게 해주는 방식이 이벤트 스토밍 기법이라고 생각한다. 이해관계자가 모여 비즈니스에 대해 고민하고 소통하면서 이해의 눈높이를 맞출 수 있는, 이 과정을 통해 단 2~3시간안에 도메인을 서브도메인으로, 다시 바운디드 컨텍스트로, 마지막엔 마이크로서비스를 식별해 낼 수 있기 때문이다. 이렇게 식별된 마이크로서비스는 스프린트 내에서 상세하게 설계되고 구현되어야 한다. 따라서 마이크로서비스를 도출했다면, 서비스간의 연관관계를 정의하고 또 서비스의 상세한 스펙을 정의해서 구현에 들어갈 준비를 마칠 수 있게된다.

여기저기 많은 자료와 서적을 찾아봐도 마이크로서비스를 식별한 후 구현에 들어가는 그 중간의 설계에 대해 설명이 없었다. 그래서 본 포스트를 통해 본격적인 구현을 위해 정의되어야 할 서비스이 상세 스펙을 찾는 방법에 대해 작성해 보았다.