- 관계형 CRUD 모델은 저장 구조는 잘 보여주지만 비즈니스 과정을 덮어쓰기 쉬워, 시스템에서 실제로 무슨 일이 일어났는지 추적하기 어려움
- Event Sourcing은 각 작업 뒤에 생긴 불변 이벤트를 Event Stream으로 남기고, 이후 의사결정에서 그 목록을 읽어 현재 상태를 판단함
- 모델링은 이벤트를 먼저 찾고, 이어 사용자의 행동 의도인 명령(command) 과 비즈니스 규칙을 연결해 프로세스를 이해하는 흐름으로 진행됨
- 기존 관계형 데이터에서 이벤트 후보를 찾을 때는 상태 컬럼, 날짜 컬럼, nullable 여부, 1:N 관계를 살피되, 상태 값만으로 완전한 이력을 복원할 수 있다고 보면 위험함
- 최종 상태만 남은 데이터를 옮길 때는 과거 이벤트를 억지로 재구성하기보다 Order Imported 같은 명시적 import 이벤트로 시작하고, 안전한 환경에서 반복 검증하는 편이 현실적임
CRUD 데이터에서 이벤트 중심 모델로 보기
- 관계형 데이터 모델은 어떤 데이터를 보관하는지는 보여주지만, 시스템 안에서 무슨 일이 일어났는지와 프로세스가 어떻게 상호작용하는지는 파악하기 어려움
- 기존 CRUD 방식은 데이터를 덮어쓰면서 중요한 비즈니스 정보를 잃을 수 있음
- Event Sourcing은 저장 크기보다 정보 품질을 우선하며, 각 작업 후 발생한 사실을 이벤트로 저장함
Event Sourcing의 기본 모델
- 이벤트는 이미 일어난 일에 대한 사실이며, 한 번 저장되면 변경할 수 없는 불변 데이터임
- Event Stream은 한 레코드에 대해 발생한 모든 일을 순서대로 담은 목록임
- 과거 이벤트를 수정할 수는 없지만, 마지막에 새 이벤트를 추가해 이전 실수를 바로잡을 수 있음
- 의사결정 시에는 이벤트 목록을 읽고 확인해 현재 상태와 다음 행동을 판단함
프로세스 모델링 순서
- 모델링은 먼저 이벤트 발견에서 시작함
- 이후 명령(command)을 찾아 어떤 행동을 실행하려는 의도인지 정의함
- 마지막으로 비즈니스 규칙을 정리함
- 이벤트는 기술 담당자와 비즈니스 담당자가 프로세스를 함께 이해하는 중심축이 됨
- Alberto Brandolini의 EventStorming처럼 이벤트, 명령, 규칙을 함께 보며 프로세스를 파악할 수 있음
기존 관계형 데이터에서 이벤트 후보 찾기
-
1. 상태 컬럼 살펴보기
- status 컬럼의 값은 데이터 생애주기의 단계를 반영할 수 있음
- 주문이 initiated, shipped, paid 같은 상태를 가진다면 각각 Order Initiated, Order Shipped, Order Paid 이벤트 후보가 될 수 있음
- 다만 상태 값은 비즈니스 프로세스를 평평하게 만든 해석일 수 있으므로, 완전하다고 가정하면 안 됨
- 이벤트 이름을 Order Created, Order Updated, Order Deleted처럼 CRUD 동작으로 붙이는 것은 피해야 함
- State Obsession은 피해야 할 방식으로 제시됨
-
2. 날짜 컬럼 확인하기
- 날짜 컬럼은 프로세스 생애주기에서 중요한 발생 시점을 알려줄 수 있음
- CreatedDate와 ModifiedDate는 많은 정보를 주지 않지만, ShipmentDate, DeliveryDate, OrderPlacementDate는 더 나은 단서가 됨
- 예시:
- ShipmentDate는 Order Shipped 이벤트 도입의 단서가 될 수 있음
- OrderPlacementDate는 Order Initiated보다 Order Placed가 더 나은 이름일 수 있음을 시사함
- DeliveryDate는 Order Delivered 이벤트가 필요할 수 있음을 보여줌
- 이런 단서는 도메인 전문가와 확인해 실제 비즈니스 프로세스와 맞춰야 함
-
3. 컬럼의 nullable 여부 분석하기
- non-nullable 컬럼은 항상 제공되어야 하는 데이터임
- nullable 컬럼은 나중에 다른 작업에서 제공되거나 선택 값일 수 있음
- Ordering Process에서 필수 컬럼이라면 해당 데이터는 첫 Order Initiated 이벤트에도 포함되어야 함
- 단일 이벤트 타입이 항상 스트림의 시작점은 아니며, 시작 이벤트는 여러 개일 수 있음
-
4. 1:N 관계가 많은 테이블 찾기
- 스트림 경계를 찾으려면 1:N 관계를 많이 가진 테이블부터 살펴볼 수 있음
- 많은 “one” 관계를 가진 테이블은 스트림 타입 후보가 됨
- 데이터가 서로 독립적으로 존재할 수 있는지도 논리적으로 판단해야 함
- shipment는 order와 별도 프로세스일 수 있음
- order line은 order 없이 존재하기 어려움
- 경계를 논의하는 과정에서 더 많은 이벤트를 발견하고 프로세스 이해를 넓힐 수 있음
마이그레이션 시 거짓 이벤트를 만들지 않기
- 관계형 데이터는 평평해진 최종 상태이므로, 그 상태만 보고 실제로 일어난 세부 과거 이벤트를 되맞추려 하면 실패하거나 부정확해질 수 있음
- 작은 단위의 과거 이벤트를 억지로 만들기보다, 현재 상태 전체와 해석 코드를 담은 Order Imported 이벤트를 명시적으로 제공하는 편이 나음
- import 이벤트는 데이터가 어떤 방식으로 들어왔는지 분명히 보여주며, 문제 해결과 진단에 중요할 수 있음
프로토타입으로 검증하기
- 마이그레이션은 안전한 환경에서 프로토타입으로 시도하고, 모델이 실제로 어떻게 움직이는지 확인해야 함
- 결과를 기대값과 비교하면서 반복적으로 수정해야 함
- 서두르지 않고 기존 정보를 잃지 않으면서, 그 정보를 바탕으로 이후 모델을 개선하는 방식이 필요함
- 관계형 데이터에서 문서 기반으로 옮기는 일반 전략은 General strategy for migrating relational data to document-based와도 연결됨