이벤트 소싱 vs CRUD: 1000개의 데이터베이스 쓰기도 중요하지 않을 때
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
데이터 분석
대상자
- 개발자 및 시스템 아키텍처 설계자
- 데이터 관리 및 이력 추적 필요성 있는 시스템 개발자
- 고확장성/고보안성이 요구되는 애플리케이션 개발자
- 난이도 관점 : 중간~고급(이력 추적, 복잡한 상태 관리 이해 필요)
핵심 요약
- CRUD = 현재 상태만 저장 (예:
user.update!(balance: 100)
) - 이벤트 소싱 = 이벤트 기반 이력 저장 (예:
BalanceAdjusted.new(...)
로 불변 이력 생성) - 이벤트 소싱의 핵심 장점
- 이력 추적 (예:
AuditLog.create!
로 변경 사항 기록) - 이력 재생 (예:
EventStore.for(user.id).sum(&:amount)
로 과거 상태 복원) - 상태 복구 (예: 이벤트 반대로 롤백 가능)
섹션별 세부 요약
1. CRUD의 한계
- 이력 상실 문제
UPDATE
명령으로 이전 데이터 복구 불가- 예: 가격을 0으로 설정한 사용자 확인 불가
- 복잡한 이력 재구성 어려움
- 과거 시스템 상태 재현 시 수동 조작 필요
2. 이벤트 소싱의 원리
- 이벤트 저장 방식
- 상태 대신 이벤트 (예:
BalanceAdjusted.new
)로 저장 - 불변 이력 생성 (예:
EventStore.publish(event)
) - 이력 기반 상태 계산
- 이벤트를 합산해 현재 상태 계산 (예:
EventStore.for(user.id).sum(&:amount)
)
3. 이벤트 소싱의 사용 사례
- 필수 조건
- 이력 추적 필요: 예: 결제 시스템 (예:
AuditLog.create!
) - 이력 재생 가능성: 예: 시스템 이력 분석 (예:
EventStore
로 특정 시간대 이력 재생) - 상태 복구 필요: 예: 주문 취소/복구 시 이벤트 롤백
- 적합하지 않은 경우
- 이력 필요 없음: 예: 사용자 프로필 (CRUD로 간단한 관리)
- 실시간 처리 요구: 예: 실시간 분석 (CRUD로 빠른 쓰기 처리)
4. 이벤트 소싱 vs CRUD 선택 기준
- 이력 추적이 필요한가? (예: 결제 시스템 → 이벤트 소싱)
- 이력 재생 가능성이 있는가? (예: 시스템 이력 분석 → 이벤트 소싱)
- 높은 빈도/낮은 가치의 쓰기인가? (예: 사용자 선호도 → CRUD)
- 최종 일관성 허용 가능한가? (예: 이벤트 소싱의 이점 활용 가능)
5. 구현 전략
- 점진적 도입
- 중요한 워크플로우 우선: 예: 결제 시스템 이벤트 소싱
- 낮은 가치 데이터는 CRUD 유지: 예: 사용자 프로필 관리
- Trade-off 측정
- 이벤트 소싱 성능 영향 분석 (예: 이벤트 재생 시 지연 문제)
결론
- 이벤트 소싱 적용 조건: 이력이 비즈니스 로직의 필수 요소일 때 (예: 결제 시스템)
- 실무 팁:
- 이벤트 소싱과 CRUD 혼합 사용 (예: 결제 이벤트 + 사용자 프로필 CRUD)
- Materialized View 사용으로 읽기 성능 최적화
- 이벤트 레코드로 불변 이력 관리 (예:
AuditLog
기록)