망고의 추천에 따라 Event Soucing에 대해 git과 함께 비교하면서 공부를 해보기로 했다..!
먼저 문서를 봐준 키리에게도 너무 감사합니다 :)
Event Sourcing (이벤트 소싱)이란?
우리는 현재 상태를 알기위해 애플리케이션의 상태를 조회할 수 있는데, 가끔은 단순한 지금의 상태가 아니라 현재 상태가 어떻게 되었는지 알고 싶은 경우가 있다. 이때 우리는 이벤트 소싱을 통해 애플리케이션 상태의 모든 변경 사항을 이벤트로 확인하고, 재구성할 수 있다.
즉 이벤트 소싱(Event Sourcing)은 애플리케이션의 상태 변화를 이벤트로 기록하고, 이 이벤트들의 시퀀스를 통해 시스템의 상태를 재구성하는 패턴을 말한다.
그렇다면 이벤트 소싱에 대해 대해 더 깊게 알아보자.
Event Sourcing의 주요 개념
이벤트(Event)란?
이벤트는 시스템의 도메인 내에서 발생한 중요한 상태 변화나 행동을 나타내는 불변의 기록을 말한다. 이는 단순한 데이터 변경이 아닌, 비즈니스적으로 의미 있는 사실(fact)을 표현한다. 아래 예시를 확인해보자.
- 은행 시스템: "계좌 개설됨(Account Opened)", "입금 완료됨(Deposit Made)", "출금 처리됨(Withdrawal Processed)"
- 전자상거래 플랫폼: "상품 장바구니에 추가됨(Product Added to Cart)", "주문 생성됨(Order Placed)", "결제 완료됨(Payment Completed)"
위에 예시와 같은 이벤트들을 통해 시스템에서 발생하는 중요한 행동을 추적하고, 이후의 상태 재구성이나 분석에 사용할 수 있다.
이때 이벤트는 한 번 기록되면 변경될 수 없는 불변(Immutable) 객체임을 명심해야한다. 그렇기에 우리는 이벤트를 과거의 기록으로 신뢰할 수 있으며, 상태 변화에 정확한 이력을 바탕으로 문제를 해결할 수 있다. 또한 이벤트 순서를 재생하면 동일한 상태를 재구성할 수 있다.
이벤트는 일반적으로 다음과 같은 속성을 포함하고 있다.
- 이벤트 타입(Event Type): 이벤트의 종류를 식별하는 명칭
- 엔티티 ID(Entity ID): 이벤트가 관련된 도메인 엔티티나 집계(Aggregate)의 식별자
- 타임스탬프(Timestamp): 이벤트가 발생한 정확한 시간
- 데이터 페이로드(Data Payload): 이벤트와 관련된 상세 정보 (ex : "입금 완료됨" 이벤트의 경우 입금 금액, 입금자 정보)
- 메타데이터(Metadata): 이벤트 처리에 필요한 추가 정보로, 이벤트 버전, 소스 시스템, 트레이싱 ID 등
우리는 이벤트를 구성할 때 이벤트에 의미 있는 이름을 부여해야하며, 최소한의 데이터를 포함시켜야 한다.
이벤트 스토어(Event Store)
이벤트 스토어는 모든 이벤트를 시간 순서대로 영구 저장하는 중앙 저장소를 말한다. 이는 단순한 데이터베이스가 아니라 이벤트 소싱 시스템의 핵심 요소로서 다음과 같은 기능을 수행한다.
- 이벤트 저장: 새로운 이벤트를 지속적으로 저장
- 이벤트 스트림 제공: 특정 엔티티나 집계에 대한 이벤트의 연속된 스트림을 제공
- 스냅샷 관리: 성능 향상을 위해 주기적인 스냅샷을 저장하고 제공
이벤트 스토어는 Append-Only 구조로 추가만 가능하며, 한 번 저장된 이벤트는 수정하거나 삭제할 수 없다. 또한 이벤트가 발생한 순서대로 저장하며, 동시에 같은 엔티티에 이벤트가 저장되려고 할 경우 경합 상항을 처리하여 저장해야 한다.
시간이 지남에 따라 이벤트 수가 많아질 경우, 모든 이벤트를 재생하는 데 걸리는 시간과 자원이 늘어나는 시점이 생기게 된다. 이때 이벤트 스토어는 스냅샷을 관리하여 비용을 감소시킬 수 있다. 스냅샷이란 특정 시점에서의 엔티티 또는 집계(Aggregate)의 현재 상태를 기록한 복사본을 말하며, 우리는 스냅샷을 통해 이벤트를 재생하지 않고 그 시점의 상태를 바로 알 수 있다.
상태 재구성(State Reconstruction)
상태 재구성은 시스템의 현재 상태를 얻기 위해 이벤트를 재생하는 과정을 말한다. 상태 재구성을 위해서는 이벤트를 로딩하고, 재생하고, 상태를 완성하는 단계를 가지고 있다. 스냅샷이 있다면, 스냅샷 상태에서 시작해서 이후의 이벤트만 재생하여 재구성 시간을 단축할 수 있다.
Git과 이벤트 소싱 비교
Git 개념 | 이벤트 소싱 개념 | 설명 |
커밋 (Commit) | 이벤트 (Event) | 커밋은 코드의 변경 사항을 저장하는 단위이며, 이벤트는 시스템에서 발생한 상태 변화를 말한다. 둘 다 이전 상태와 변경된 내용을 포함하며, 불변이다. |
저장소 (Repository) | 이벤트 스토어 (Event Store) | Git 저장소는 모든 커밋과 브랜치를 저장하는 곳을 말하며, 이벤트 스토어는 모든 이벤트를 시간 순서대로 저장하는 중앙 저장소이다. 둘 다 상태 변화에 대해 시간 순서대로 저장하여 시스템의 상태 변화를 추적한다. |
브랜치 (Branch) | 스트림 (Stream) | 특정 엔티티나 집계에 대한 이벤트의 연속된 흐름으로, 독립적인 상태 변화를 |
로그 (Log) | 이벤트 히스토리 (Event History) | Git 로그는 커밋의 역사적 기록을 말하며, 이벤트 히스토리는 시스템에서 발생한 모든 이벤트의 기록을 말한다. |
다음에 CQRS에 대해서도 공부해봐야겠다!