[기획] 이벤트 스토밍 도입기

2025. 11. 28. 23:24·스파르타 자바 심화 4기 RushCrew Project
스파르타 내일배움캠프 Java 심화 4기, 'RushCrew' 팀의 타임딜 프로젝트를 진행하며 
이벤트 스토밍을 적용했던 배경과 진행 과정, 진행 후 느낀점 기록입니다.

   

1. 도입 배경

이전 물류 시스템 프로젝트를 개발할 때의 일이다. 

기획서만 믿고 개발을 진행했는데, 막상 결과물을 통합하려는 순간 문제가 발생했다.

 

(주문팀) "주문 쪽에서 허브(공급 업체)를 호출하는 거 아니었나요?"

(배달팀) "아니죠, 배달 쪽에서 허브를 호출해서 데이터를 가져가는 구조로 이해했는데요?" 

 

텍스트로 된 기획서의 문장 읽고 서로 주체와 객체를 다르게 해석한 것이다.

이 '해석의 차이'로 인해 결국 재작업과 코드를 뜯어고치고 더 많은 시간을 썼던지..

 

이러한 실수를 줄이기 위한 방법을 찾던 중

DDD(Domain-Driven Design)의 핵심 방법론인 '이벤트 스토밍' 을 알게 되었고

이번 프로젝트는 처음부터 이벤트 스토밍을 도입해 진행하도록 하였다. 


2. 이벤트 스토밍이란?

이벤트 스토밍은 복잡한 비즈니스 도메인을 벽면에 포스트잇으로 시각화하여, 기획자, 개발자, 도메인 전문가가 같은 이해(Mental Model)를 갖게 하는 DDD(Domain-Driven Design) 워크숍

이벤트 스토밍 표기 요소

목적

  • 개발자, 기획자, 현업 모두가 한 장의 보드에서 동일한 언어로 대화
  • 도메인에 대한 공통 이해(Shared Understanding) 확보
  • 문서 없이도 시각적으로 문제를 파악

3. 진행 단계 

3-1. 빅 픽처

전체적인 비즈니스의 흐름을 파악하고, 참여자 간의 공통된 이해(Mental Model)를 맞추는 단계

이벤트 포스트지

목적

  • 전체적인 구조와 흐름을 이해
  • 도메인에 대한 공통된 이해를 목표

 

진행방식

서비스에 맞는 도메인 이벤트들을 적어서 붙이며 진행하면 된다.

이 단계의 핵심은 토론은 지양하고, 각자의 자신의 생각대로 이벤트를 적어서 붙인다.

 

Insight

처음에는 눈치만 보며 어색해 하였지만 하나씩 붙이며, 금방 채워져갔던 거 같다.

이 과정은 단순한 포스트잇 부착 작업을 넘어, 팀의 분위기를 풀어주는 자연스러운 아이스브레이킹 되고, 여러 상황을 생각해 보면서 프로젝트의 요구사항을 깊이 있게 이해하는 시간이었던 거같다.

 

3-2. 프로세스 모델링

빅 픽처에서 도출된 흐름을 더 상세히 분석하고, 이벤트가 발생하는 구체적인 원인과 조건을 정의
관련된 커맨드, 액터, 시스템, 정책, 데이터 요구사항, 비즈니스 규칙 등을 추가

 

목적

  • 비즈니스 프로세스의 상세 분석 및 워크플로우 시각화

 

주요 구성 요소:

  • 커맨드 (Command): 도메인 이벤트를 유발하는 명령 (사용자의 의도).
    • 예) '주문 생성됨' 이벤트의 커맨드 → '주문 요청'
  • 액터 (Actor): 커맨드를 실행하는 주체 (구체적인 사용자 역할).
    • 시스템이 자동으로 실행하는 경우 액터를 생략하거나 '시스템'으로 표기.
  • 정책 (Policy): "이벤트가 발생하면(Whenever), ~을 한다(Then)" 형식의 리액티브 로직.
    • 예) 주문이 완료되면 → 배송 업무가 시작된다.
  • 외부 시스템 (External System): 도메인 외부와 상호작용하는 시스템 (결제 모듈, 알림 서비스 등).

 

진행 방식

  1. 커맨드와 액터 식별
    • 커맨드(명령), 액터(사용자 또는 시스템)를 식별(뽑아냄)
    • 예) [구매자] -> [주문 요청] -> (주문 생성됨)
  2. 외부 시스템 식별
    • 이벤트가 외부 서비스(PG사, 배송 업체 등)를 통해 발생하거나 호출하는 경우 표시
  3. 정책 및 규칙 추가
    • 이벤트 발생 후 연이어 수행되어야 하는 비즈니스 규칙을 정의
    • Whenever(이벤트가 발생하면) -> Then(무엇을 한다) 형식으로 작성하여 이벤트 뒤(오른쪽)에 붙인다.
    • 예) (주문 취소됨) -> [정책: 환불 절차를 시작한다]

 

Insight

이 과정에서 가장 큰 수확은 공통된 언어로 통일이라고 생각이 든다.

누군가는 상품 등록 주체를 '담당자'라 불렀고, 누군가는 '판매자'라고 불렀다.

사소해 보이지만 이는 소통에서 커뮤니케이션 비용을 증가 시키고 DB 테이블명과 코드의 클래스명까지 갈라놓을 수 있는 문제가 될 수 있는 문제이다.

 

논의 끝에 판매자로 용어를 통일하였고,

이 합의 덕분에 이후 개발 단계에서 변수명 하나를 짓는 데 드는 고민 시간을 단축시켰지 않았나 생각이 든다.

 

3-3. 소프트웨어 디자인(Software Design) 단계

비즈니스 로직을 실제 구현 가능한 수준으로 구체화하는 단계
연관된 포스트잇들을 묶어 애그리거트(Aggregate/데이터 변경의 단위)를 정의하고, 바운디드 컨텍스트(Bounded Context)를 그려 마이크로서비스(MSA)의 경계를 설정

 

목적

  • 트랜잭션의 범위(Transaction Boundary) 결정
  • 서비스 간의 의존성 분리 및 통신 방식 결정

 

진행 방식

  1. 애그리거트(Aggregate) 정의 
    • 연관된 커맨드와 이벤트를 묶어, 상태 변경의 단위(트랜잭션 범위)를 그룹화한다.
    • 도메인의 상태를 책임지는 객체의 이름을 정한다. (예: Order, Payment)
  2. 바운디드 컨텍스트(Bounded Context) 경계 설정
    • 애그리거트들을 감싸는 경계를 표시한다. 이것이 MSA로 분리할 수 있는 잠재적인 서비스 후보가 된다.
  3. 리드 모델(Read Model) 설계 (초록색 포스트잇)
    • 사용자가 의사결정을 하기 위해 화면에 보여져야 할 데이터 정보를 정의
    • 어떤 이벤트의 데이터가 조합되어야 하는지 파악

 

Insight

 

3단계 디자인 과정은 우리 팀이 '데이터 효율성'과 '확장성' 사이에서 가장 오랫동안, 그리고 치열하게 논쟁했던 단계이다.

 

주제는 "타임딜 상품 테이블을 별도로 분리할 것인가, 아니면 기존 상품 컨텍스트 안에서 통합 관리할 것인가"였다.

 

우리는 "상품은 변하지 않는 자산이고, 타임딜은 찰나의 이벤트"라는 본질적인 차이에 주목했다.

생명주기가 완전히 다른 두 영역을 하나의 도메인에 섞을 수는 없었기에, 물리적으로 도메인(Context)을 명확히 분리하는 결정을 내렸다.

 

또한 트래픽 폭주 시 원본 DB에 락(Lock)이 걸려 전체 서비스가 마비되는 치명적인 위험을 막아야 했다.

이를 위해 Redis Write-Behind(지연 쓰기) 전략을 도입하여, 순간적인 부하를 캐시 계층에서 흡수하고 DB에는 비동기로 반영함으로써 시스템의 안정성을 확보하도록 설계하였다.

 

결론적으로 우리는 '데이터 중복'이라는 기술적 부채를 기꺼이 감수하고 '서비스 격리'를 선택했다.

이 치열한 논쟁과 결정 덕분에, 타임딜 트래픽이 아무리 폭주해도 메인 쇼핑몰은 안전하게 보호되는 더 견고하고 확장 가능한 아키텍처를 완성할 수 있었고, 긴 이벤트 스토밍을 성공적으로 마무리 할 수 있었다.


4. 느낀점 

이벤트 스토밍을 도입하면서 얻은 가장 큰 수확은 역설적이게도 화려한 아키텍처가 아니라 '팀의 언어 통일'이라고 생각한다.

 

이전 프로젝트에서는 "그거 있잖아요"라며 서로 다른 단어로 소통하느라 낭비되는 시간이 정말 많았는데..

이번에는 모두 약속된 단어 하나로 명쾌하게 소통하였고 '언어'가 통일되니 '오해'가 사라졌고, 자연스럽게 커뮤니케이션 비용이 줄어든게 체감이 되었다.

 

또한, 본격적인 코딩 전에 각 도메인의 기술적 제약을 미리 공유할 수 있었던 점도 좋았던가 같다.

덕분에 발생 가능한 예외를 미리 시나리오에 포함시킬 수 있었고, 불확실성을 크게 낮출 수 있을 것으로 보인다.

 

무엇보다 이번 과정을 통해 단순히 기능을 구현하는 것을 넘어, 데이터의 흐름과 비즈니스 임팩트까지 함께 고민하는 진짜 '엔지니어링'을 경험했다는 점에서 개발자로서 한 단계 성장할 수 있었던 시간이었다고 생각한다.

진행 하였던 이벤트 스토밍 결과물


5. 참고

  • https://miro.com/app/board/uXjVJlCZnJY=/

'스파르타 자바 심화 4기 RushCrew Project' 카테고리의 다른 글

[의사결정] MSA 설계 시 동기·비동기 통신 선택 가이드  (0) 2025.12.15
[트러블 슈팅] 로그아웃 API 구현 과정과 개선 기록  (0) 2025.12.06
[트러블 슈팅] Java 21 업그레이드 후 Eureka DNS 해석 실패  (1) 2025.12.02
'스파르타 자바 심화 4기 RushCrew Project' 카테고리의 다른 글
  • [의사결정] MSA 설계 시 동기·비동기 통신 선택 가이드
  • [트러블 슈팅] 로그아웃 API 구현 과정과 개선 기록
  • [트러블 슈팅] Java 21 업그레이드 후 Eureka DNS 해석 실패
코드피터
코드피터
능동적으로 배우고, 적극적으로 해결하며, 성실하게 성장
  • 코드피터
    코드 읽어주는 피터
    코드피터
  • 전체
    오늘
    어제
    • 분류 전체보기 (10)
      • 이슈 (1)
      • 트러블 슈팅 (1)
      • 아키텍처 (3)
      • Backend (1)
      • 스파르타 자바 심화 4기 RushCrew Proj.. (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    외부 API 연동
    RestClient
    Spring Boot
    backend
    SystemDesign
    #DDD
    JEP 418
    Monolithic
    이벤트스토밍
    트러블 슈팅
    Java 21 Features
    fetch join
    N+1
    SagaPattern
    멱등성
    springboot
    HHH000104
    분산트랜잭션
    MSA
    Netflix Eureka
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
코드피터
[기획] 이벤트 스토밍 도입기
상단으로

티스토리툴바