Gidhub BE Developer

[데이터 중심 애플리케이션 설계] 11장. 스트림 처리 : 2. DB와 스트림 - 2편

2022-06-23
goodGid

이 글은 내용을 토대로 작성하였습니다.

목차

  1. 이벤트 스트림 전송 - 1편

  2. 이벤트 스트림 전송 - 2편

  3. DB와 스트림 - 1편

  4. DB와 스트림 - 2편

  5. 스트림 처리 - 1편

  6. 스트림 처리 - 2편


이벤트 소싱

  • 이벤트 소싱은 도메인 주도 설계에서 개발한 기법이다.

  • CDC와 비슷하게 어플리케이션 상태 변화를 모두 변경 이벤트 로그로 저장한다.

    다만 CDC와 추상화 레벨이 다르다.

- CDC에서 어플리케이션은 DB에 있는 데이터에 대해 자유롭게 "추가/수정/삭제" 작업이 가능하다.
- 변경 로그의 순서는 DB에서 추출한 쓰기 순서와 실제로 데이터를 기록한 순서와 일치하다.
- 이벤트 소싱에서 어플리케이션 로직은 이벤트 로그에 기록된 불변 이벤트를 기반으로 명시적으로 구축한다.
- 이때 이벤트 저장은 단지 "추가"만 가능하고 "수정/삭제" 작업은 권장하지 않거나 금지한다.
  • 이벤트 소싱을 사용하면 어플리케이션을 지속해서 개선하기가 매우 유리하다.

    어떤 상황이 발생한 후에 상황 파악이 쉬우므로

    디버깅에 도움이 되고 어플리케이션 버그를 방지한다.

  • 예를 들어 “어떤 학생이 강의 신청을 취소했다”는 이벤트를 저장한다고 하자.

    이 동작은 단일 동작의 의도를 중립적인 방식으로 표현한다.

  • 반면 이 동작의 사이드 이펙은

    “수강 테이블에서 항목 하나를 삭제하고 학생 피드백 테이블에 취소 사유를 추가한다.”는 데이터가

    나중에 사용되는 방식에 관한 많은 가정을 포함한다.

  • 만약 어플리케이션에

    “대기 목록의 다음 사람에게 자리를 제공”하라는 새로운 기능을 추가하더라도

    이벤트 소싱 접근법을 사용하면

    새로 발생한 사이드 이펙을 기존 이벤트에서 쉽게 분리할 수 있다.


이벤트 로그에서 현재 상태 파생하기

  • 이벤트 로그는 그 자체는 가치가 없다.

  • 사용자는 시스템의 현재 상태를 보기 원하지 수정 히스토리를 원하지 않기 때문이다.

    ex) 쇼핑 장바구니에 발생한 모든 변경 사항을 기록한 추가 전용 목록이 아니라

    현재 장바구니의 내용을 보고 싶어한다.

  • 따라서 이벤트 소싱을 사용하는 어플리케이션은

    시스템에 기록한 데이터를 표현한 이벤트 로그를 가져와

    사용자에게 보여주기에 적당하게 변환해야 한다.

  • CDC와 마찬가지로 이벤트 로그를 재현하면

    현재 시스템 상태를 재구성할 수 있다.

    하지만 로그 컴팩션은 다르게 처리해야 한다.

  • 레코드 갱신용 CDC 이벤트는 레코드의 가장 새로운 버전을 보유한다.

    그래서 기본키의 현재 값은 기본 키의 가장 최신 이벤트로 결정되고

    같은 키의 이전 이벤트는 로그 컴팩션을 통해 버린다.

  • 반면 이벤트 소싱은 이벤트를 보다 상위 수준에서 모델링한다.

  • 이벤트는 대개 사용자 행동의 결과로 발생한 상태 갱신 메커니즘이 아닌

    사용자 행동 의도를 표현한다.

    이 경우 뒤에 발생한 이벤트가 앞선 이벤트를 덮어쓰지 않는다.

  • 그래서 마지막 상태를 재구축하기 위해서는

    이벤트의 전체 히스토리가 필요하다.

    이런 방식에서는 로그 컴팩션이 불가능하다.

  • 이벤트 소싱을 사용하는 어플리케이션은

    일반적으로 이벤트 로그에서 파생된 현재 상태의 스냅샷을 저장하는 메커니즘이 있으므로

    전체 로그를 반복해서 재처리할 필요는 없다.

  • 하지만 이 메커니즘은 장애 발생 시

    읽고 복구하는 성능을 높여주는 최적화에 불과하다.

  • 이벤트 소싱 시스템에는 모든 원시 이벤트를 영원히 저장하고

    필요할 때마다 모든 이벤트를 재처리할 수 있어야 한다는 의도가 있다.


상태와 스트림 그리고 불변성

동일한 이벤트 로그로 여러 가지 뷰 만들기

  • 같은 이벤트 로그로 다른 여러 읽기 전용 뷰를 만들 수 있다.

  • 기존 데이터를 새로운 방식으로 표현하는 새 기능을 추가하려면

    이벤트 로그를 사용해 신규 기능용으로 분리한 읽기 최적화된 뷰를 구축할 수 있다.

  • 또한 기존 시스템을 수정할 필요가 없고

    기존 시스템과 함께 운용할 수 있다.


동시성 제어

  • 이벤트 소싱CDC가장 큰 단점

    이벤트 로그의 소비가 비동기로 이뤄진다는 점이다.

  • 그래서 사용자가 로그에 이벤트를 기록하고

    이어서 로그에서 파생된 뷰를 읽어도

    기록한 이벤트가 아직 반영되지 않았을 가능성이 있다.

  • 해결책 중 하나로는 읽기 뷰의 갱신과

    로그에 이벤트를 추가하는 작업을 동기식으로 수행하는 방법이다.

  • 이 방법을 쓰려면 트랜잭션에서 여러 쓰기를 원자적 단위로 결합해야 하므로

    이벤트 로그와 읽기 뷰를 같은 저장 시스템에 담아야한다.

  • 만약 다른 시스템에 얽혀있다면 분산 트랜잭션이 필요하다.


불변성의 한계

  • 데이터가 모두 불변성임에도 관리상의 이유로 데이터를 삭제할 필요가 있다.

  • 이런 상황에서는 “이전 데이터를 삭제해야 한다.”는

    이벤트를 로그에 추가하는 식으로는 문제를 해결할 수 없다.

  • 근본적으로 문제가 되는 데이터를 처음부터 기록하지 않은 상태로 되돌려야 한다.

  • 또한 데이터를 진짜로 삭제하는 작업은 굉장히 어렵다.

    많은 곳에 복제본이 남아 있으므로 그 모든 곳을 다 찾아야 하기 때문이다.


Refernece


Recommend

Index