이 글은 책 내용을 토대로 작성하였습니다.
목차
이벤트 소싱
-
이벤트 소싱은 도메인 주도 설계에서 개발한 기법이다.
-
CDC와 비슷하게 어플리케이션 상태 변화를 모두 변경 이벤트 로그로 저장한다.
다만 CDC와 추상화 레벨이 다르다.
- CDC에서 어플리케이션은 DB에 있는 데이터에 대해 자유롭게 "추가/수정/삭제" 작업이 가능하다.
- 변경 로그의 순서는 DB에서 추출한 쓰기 순서와 실제로 데이터를 기록한 순서와 일치하다.
- 이벤트 소싱에서 어플리케이션 로직은 이벤트 로그에 기록된 불변 이벤트를 기반으로 명시적으로 구축한다.
- 이때 이벤트 저장은 단지 "추가"만 가능하고 "수정/삭제" 작업은 권장하지 않거나 금지한다.
-
이벤트 소싱을 사용하면 어플리케이션을 지속해서 개선하기가 매우 유리하다.
어떤 상황이 발생한 후에 상황 파악이 쉬우므로
디버깅에 도움이 되고 어플리케이션 버그를 방지한다.
-
예를 들어 “어떤 학생이 강의 신청을 취소했다”는 이벤트를 저장한다고 하자.
이 동작은 단일 동작의 의도를 중립적인 방식으로 표현한다.
-
반면 이 동작의 사이드 이펙은
“수강 테이블에서 항목 하나를 삭제하고 학생 피드백 테이블에 취소 사유를 추가한다.”는 데이터가
나중에 사용되는 방식에 관한 많은 가정을 포함한다.
-
만약 어플리케이션에
“대기 목록의 다음 사람에게 자리를 제공”하라는 새로운 기능을 추가하더라도
이벤트 소싱 접근법을 사용하면
새로 발생한 사이드 이펙을 기존 이벤트에서 쉽게 분리할 수 있다.
이벤트 로그에서 현재 상태 파생하기
-
이벤트 로그는 그 자체는 가치가 없다.
-
사용자는 시스템의 현재 상태를 보기 원하지 수정 히스토리를 원하지 않기 때문이다.
ex) 쇼핑 장바구니에 발생한 모든 변경 사항을 기록한 추가 전용 목록이 아니라
현재 장바구니의 내용을 보고 싶어한다.
-
따라서 이벤트 소싱을 사용하는 어플리케이션은
시스템에 기록한 데이터를 표현한 이벤트 로그를 가져와
사용자에게 보여주기에 적당하게 변환해야 한다.
-
CDC와 마찬가지로 이벤트 로그를 재현하면
현재 시스템 상태를 재구성할 수 있다.
하지만 로그 컴팩션은 다르게 처리해야 한다.
-
레코드 갱신용 CDC 이벤트는 레코드의 가장 새로운 버전을 보유한다.
그래서 기본키의 현재 값은 기본 키의 가장 최신 이벤트로 결정되고
같은 키의 이전 이벤트는 로그 컴팩션을 통해 버린다.
-
반면 이벤트 소싱은 이벤트를 보다 상위 수준에서 모델링한다.
-
이벤트는 대개 사용자 행동의 결과로 발생한 상태 갱신 메커니즘이 아닌
사용자 행동 의도를 표현한다.
이 경우 뒤에 발생한 이벤트가 앞선 이벤트를 덮어쓰지 않는다.
-
그래서 마지막 상태를 재구축하기 위해서는
이벤트의 전체 히스토리가 필요하다.
이런 방식에서는 로그 컴팩션이 불가능하다.
-
이벤트 소싱을 사용하는 어플리케이션은
일반적으로 이벤트 로그에서 파생된 현재 상태의 스냅샷을 저장하는 메커니즘이 있으므로
전체 로그를 반복해서 재처리할 필요는 없다.
-
하지만 이 메커니즘은 장애 발생 시
읽고 복구하는 성능을 높여주는 최적화에 불과하다.
-
이벤트 소싱 시스템에는 모든 원시 이벤트를 영원히 저장하고
필요할 때마다 모든 이벤트를 재처리할 수 있어야 한다는 의도가 있다.
상태와 스트림 그리고 불변성
동일한 이벤트 로그로 여러 가지 뷰 만들기
-
같은 이벤트 로그로 다른 여러 읽기 전용 뷰를 만들 수 있다.
-
기존 데이터를 새로운 방식으로 표현하는 새 기능을 추가하려면
이벤트 로그를 사용해 신규 기능용으로 분리한 읽기 최적화된 뷰를 구축할 수 있다.
-
또한 기존 시스템을 수정할 필요가 없고
기존 시스템과 함께 운용할 수 있다.
동시성 제어
-
이벤트 소싱 과 CDC 의 가장 큰 단점은
이벤트 로그의 소비가 비동기로 이뤄진다는 점이다.
-
그래서 사용자가 로그에 이벤트를 기록하고
이어서 로그에서 파생된 뷰를 읽어도
기록한 이벤트가 아직 반영되지 않았을 가능성이 있다.
-
해결책 중 하나로는 읽기 뷰의 갱신과
로그에 이벤트를 추가하는 작업을 동기식으로 수행하는 방법이다.
-
이 방법을 쓰려면 트랜잭션에서 여러 쓰기를 원자적 단위로 결합해야 하므로
이벤트 로그와 읽기 뷰를 같은 저장 시스템에 담아야한다.
-
만약 다른 시스템에 얽혀있다면 분산 트랜잭션이 필요하다.
불변성의 한계
-
데이터가 모두 불변성임에도 관리상의 이유로 데이터를 삭제할 필요가 있다.
-
이런 상황에서는 “이전 데이터를 삭제해야 한다.”는
이벤트를 로그에 추가하는 식으로는 문제를 해결할 수 없다.
-
근본적으로 문제가 되는 데이터를 처음부터 기록하지 않은 상태로 되돌려야 한다.
-
또한 데이터를 진짜로 삭제하는 작업은 굉장히 어렵다.
많은 곳에 복제본이 남아 있으므로 그 모든 곳을 다 찾아야 하기 때문이다.