소프트웨어 공학 100 주제 시리즈의 18번째 글이다. (카테고리: 요구사항 공학)

한 줄 요약

이벤트 스토밍은 도메인 전문가와 개발자가 긴 벽 앞에서 “무슨 일이 일어났나” 를 과거형 주황 스티커로 시간순으로 붙여 가며 업무 전체를 함께 그리는 워크숍이다. 요구사항을 한 사람씩 인터뷰해서는 보이지 않는 부서 간 경계, 용어 충돌, 아무도 책임지지 않는 구간을 몇 시간 만에 드러낸다.

왜 필요한가

요구 도출의 기본기는 인터뷰다. 그런데 업무가 여러 부서를 거치면 인터뷰는 구조적으로 실패한다.

  • 주문팀은 “주문 완료” 가 결제 승인이라고 말하고, 물류팀은 출고 확정이라고 말한다. 각자의 인터뷰 기록은 모두 맞다. 합쳐 보면 모순이다.
  • 업무의 진짜 문제는 부서 사이에 있다. 한 부서는 “넘겼다” 고 하고 다음 부서는 “받은 적 없다” 고 한다. 어느 인터뷰에도 그 틈은 나오지 않는다.
  • 분석가가 인터뷰를 모아 문서를 만드는 동안 몇 주가 가고, 그 문서를 검토하는 사람은 자기 부분만 읽는다.

도메인 주도 설계의 보편 언어와 바운디드 컨텍스트는 이 문제를 겨냥한 개념이지만, “어떻게 찾느냐” 는 별개 문제다. 이벤트 스토밍은 그 발견 방법이다.

핵심 개념

원전과 기본 규칙

Alberto Brandolini 는 2013년 블로그 글 Introducing Event Storming에서 기본 단계를 이렇게 적었다.

  1. 맞는 사람을 초대한다. 넓은 회의실에 6~8명, 질문할 줄 아는 사람(그리고 답을 궁금해하는 사람)과 답을 아는 사람을 섞는다.
  2. 모델링 공간을 무제한으로 준다. 복잡한 문제가 제대로 분석되지 못하는 이유는 문제를 볼 공간이 부족해서다. 문제는 화이트보드보다 크다. 그는 이케아 종이 롤을 즐겨 쓴다고 했다.
  3. 도메인 이벤트부터 탐색한다. 도메인 이벤트는 도메인에서 일어난 의미 있는 일이다. 소프트웨어로 쉽게 옮길 수 있지만, 진짜 가치는 비기술자도 금방 이해한다는 점이다. 관례상 주황 스티커에 쓰고 시간순으로 붙인다.
  4. 이벤트의 원인을 찾는다. 사용자 행동의 결과라면 명령(파란 스티커), 외부 시스템이나 시간의 흐름 때문이라면 그것을 표시한다.

이후 기법이 다듬어져 지금은 eventstorming.com과 Brandolini 의 Leanpub 책 Introducing EventStorming이 공식 자료다.

왜 “이벤트” 부터인가

명사부터 시작:  "주문, 고객, 상품, 쿠폰…"  → 데이터 모델 논쟁, 속성 목록
동사부터 시작:  "주문하다, 결제하다…"     → 누가 하느냐 논쟁
이벤트부터 시작: "주문이 접수됨, 결제가 승인됨, 음료가 준비됨…"
               → 일어난 사실이라 반박하기 어렵고, 시간순으로 줄을 세울 수 있다

과거형 사실은 각 부서가 자기 언어로 쓰더라도 시간축 위에서 충돌한다. “주문 완료됨” 스티커 두 장이 서로 다른 위치에 붙는 순간, 그 단어가 두 가지 뜻이라는 것이 모두에게 보인다. 이것이 인터뷰로는 안 되던 일이다.

스티커 문법

DDD 커뮤니티가 정리한 EventStorming Glossary & Cheat sheet의 색 규칙이다.

색 개념 설명
주황 도메인 이벤트 도메인 전문가에게 의미 있는 사건. 과거형 동사
형광 분홍(기울여 붙임) 핫스팟 충돌·마찰·질문·이견·나중에 팔 문제
초록 기회(opportunity) 핫스팟의 긍정 버전. 타임라인 정리 후 사용
작은 노랑 행위자 사람, 팀, 부서
넓은 분홍 시스템 배포 가능한 IT 시스템. 엑셀일 수도 있다
파랑 명령/행동 결정·행동·의도
라일락 정책 “X 가 일어나면 Y 한다” 는 반응
초록 조회 모델 행위자가 결정에 필요한 정보
큰 노랑 제약 명령 수행 시 지켜야 할 규칙. 예전엔 애그리거트라 불렀다

색 자체는 중요하지 않다. 범례를 벽에 붙여 두고 모두가 같은 문법을 쓰는 것이 중요하다.

세 가지 수준

수준 목표 참여자 결과
빅 픽처 사업 전체의 건강 진단, 새 사업 모델 탐색 10~30명 이상, 여러 부서 전체 타임라인, 핫스팟, 떠오르는 바운디드 컨텍스트
프로세스 모델링 한 흐름을 명령·정책·조회 모델까지 상세화 해당 흐름 관계자 프로세스 규칙, 정책
소프트웨어 설계 이벤트·명령·제약으로 설계 단위 도출 개발자 + 도메인 전문가 제약(애그리거트) 경계, 이벤트 계약

빅 픽처 결과는 콘웨이 법칙에 맞춰 팀과 소프트웨어를 업무 흐름 중심으로 정렬하는 입력으로도 쓸 수 있다고 cheat sheet 는 설명한다.

빅 픽처 진행 순서

1. 혼돈의 탐색  각자 아는 이벤트를 조용히 쓴다. 서로 영향을 주지 않도록 토론 금지
       │
2. 타임라인 강제  중복 제거, 순서 정리. 시끄러워지는 게 정상
       │         "같은 말, 다른 뜻" 이 여기서 드러난다
3. 핫스팟       충돌·질문은 그 자리에서 해결하지 말고 분홍 스티커로 표시
       │
4. 개념 추가     행위자, 시스템, 가치, 기회 … 필요할 때만 범례에 추가
       │
5. 핵심 이벤트·경계  흐름을 바꾸는 중요한 이벤트(pivotal event)로 구간을 나눈다
                → 떠오르는 바운디드 컨텍스트 후보

진행자는 중립을 지키며, 긴 논쟁을 끊고 핫스팟으로 시각화한다. 완성도를 목표로 하지 않는다. Brandolini 는 모델이 거대해지므로 완성은 별 가치가 없고, 불완전함을 받아들여야 워크숍이 생산적이라고 썼다.

예제

커피 주문 앱 빅 픽처의 한 구간

시간 ─────────────────────────────────────────────────────────────▶
[고객]      [고객]        [결제 대행사]   [바리스타]     [바리스타]    [고객]
주문이       결제가        결제가          제조가          음료가        음료를
접수됨  ──▶  요청됨  ──▶   승인됨   ──▶    시작됨   ──▶    준비됨  ──▶   수령함
                            │                                 │
                    ⚠ 승인 알림이 두 번                 ⚠ 고객이 10분째 안 옴.
                      오면? (핫스팟)                     폐기? 보관? 누가 결정? (핫스팟)
                            │
                   ◇ 정책: 결제가 승인되면
                     제조를 시작한다

이 그림에서 요구사항 두 개가 나왔다. “승인 알림 중복 시 한 번만 반영한다”, “미수령 음료 처리 규칙을 정한다”. 둘 다 인터뷰에서는 아무도 말하지 않았던 것이다.

설계 수준으로 내려가기

소프트웨어 설계 단계에서 스티커는 코드 구조로 거의 그대로 옮겨진다. 과거형 이벤트는 불변 객체로, 큰 노랑(제약)은 규칙을 지키는 객체로, 라일락(정책)은 이벤트에 반응하는 함수로.

from dataclasses import dataclass

@dataclass(frozen=True)          # 주황: 과거형 이름의 불변 이벤트
class 결제가_승인됨:
    주문번호: str
    금액: int

@dataclass(frozen=True)
class 제조가_시작됨:
    주문번호: str

class 주문:                       # 큰 노랑: 규칙을 지키며 명령을 받아 이벤트를 낸다
    def __init__(self, 번호):
        self.번호, self.결제됨, self.이벤트 = 번호, False, []

    def 결제_승인_반영(self, 금액):   # 파랑: 명령
        if self.결제됨:               # 핫스팟에서 나온 규칙: 중복 승인 무시
            return
        self.결제됨 = True
        self.이벤트.append(결제가_승인됨(self.번호, 금액))

def 결제되면_제조를_시작한다(e):    # 라일락: "X 가 일어나면 Y 한다"
    if isinstance(e, 결제가_승인됨):
        return 제조가_시작됨(e.주문번호)

o = 주문("A-17")
o.결제_승인_반영(4500)
o.결제_승인_반영(4500)            # 결제 대행사가 승인 알림을 두 번 보낸 경우
for e in o.이벤트:
    print(e, "→", 결제되면_제조를_시작한다(e))
결제가_승인됨(주문번호='A-17', 금액=4500) → 제조가_시작됨(주문번호='A-17')

워크숍 언어와 코드 언어가 같다. 이것이 Martin Fowler 가 UbiquitousLanguage에서 설명하는, 개발자와 사용자가 공유하는 엄밀한 언어를 만드는 실제 경로다. 코드에서 이벤트를 다루는 패턴은 Fowler 의 Domain Event 를 참고한다.

준비 체크리스트

  • 목표를 한 문장으로 초대장에 쓴다(“주문 취소가 왜 이렇게 오래 걸리는지 찾는다”).
  • 지식을 가진 사람과 그 지식이 필요한 사람을 모두 부른다. 결정권자 한 명은 꼭.
  • 6~8m 이상의 벽, 종이 롤, 색별 스티커, 사람 수만큼의 마커. 의자는 치운다.
  • 범례를 눈에 띄게 붙인다.
  • 원격이라면 온라인 화이트보드에 같은 범례를 미리 깐다.

흔한 오해와 함정

  • 처음부터 설계 수준으로 간다. 빅 픽처 없이 애그리거트부터 찾으면 개발자끼리의 모델링 회의가 된다. 도메인 전문가가 빠진 이벤트 스토밍은 이름만 같다.
  • 현재형·명령형 이벤트. “주문하기”, “결제 처리” 는 이벤트가 아니다. “주문이 접수됨” 처럼 과거형 사실로 쓰게 유도한다. 과거형이어야 시간순 배치와 반박이 가능하다.
  • 핫스팟을 그 자리에서 해결한다. 한 쟁점에 30분을 쓰면 나머지 흐름을 못 본다. 표시하고 넘어간 뒤 따로 다룬다.
  • 스티커 사진이 산출물이다. 결과는 결정과 질문 목록이다. 핫스팟마다 담당자와 후속 조치를 정하지 않으면 워크숍은 즐거운 행사로 끝난다.
  • 바운디드 컨텍스트가 워크숍에서 확정된다. 빅 픽처가 주는 것은 “떠오르는” 경계 후보다. 설계 수준 탐색과 실제 코드로 검증해야 한다.

확인 문제

  1. Brandolini 가 “무제한 모델링 공간” 을 강조한 이유는?
  2. 이벤트를 과거형으로 쓰면 무엇이 좋은가?
  3. 핫스팟과 기회 스티커의 차이는?
  4. 빅 픽처와 소프트웨어 설계 수준 이벤트 스토밍의 참여자와 산출물은 어떻게 다른가?
  5. 예제의 “승인 알림이 두 번 오면?” 핫스팟이 어떤 요구사항과 코드 규칙으로 이어졌는가?

풀이

  1. 복잡한 문제를 제대로 분석하지 못하는 이유가 문제를 한눈에 볼 공간이 부족해서이기 때문이다. 문제는 화이트보드보다 크다.
  2. 일어난 사실이라 반박하거나 확인하기 쉽고, 시간순으로 배치할 수 있어 부서 간 용어 충돌과 순서 모순이 시간축 위에서 드러난다.
  3. 핫스팟은 충돌·질문·문제(부정적)를, 기회는 개선 가능성(긍정적)을 표시한다. 기회는 타임라인을 정리한 뒤 쓴다.
  4. 빅 픽처는 여러 부서 10~30명 이상이 사업 흐름 전체를 그려 핫스팟과 경계 후보를 얻는다. 설계 수준은 개발자와 도메인 전문가가 명령·이벤트·제약을 찾아 설계 단위를 정한다.
  5. “같은 주문의 결제 승인은 한 번만 반영한다” 는 요구가 됐고, 코드에서는 주문 객체가 이미 결제됐으면 승인 명령을 무시하는 규칙으로 구현됐다.

더 읽을거리 (References)