서론

당근 Server 밋업에서 원지혁님의 이벤트 소싱 관련 발표에서 이벤트 소싱을 이해하는데 많은 도움이 되었었습니다.. 이벤트 소싱의 기본적인 개념을 정리하고, 발표 내용을 바탕으로 NestJS, TypeScript, MongoDB 기반의 컨피그 서비스를 간단히 만들어보았습니다.

이벤트 소싱의 기본 개념

  • 기존 CRUD 방식과 달리, 모든 상태 변경을 불변 이벤트로 기록하여 감사 추적과 롤백이 용이함
  • 회계 장부처럼 모든 거래(이벤트)를 순차적으로 기록해, 언제든지 현재 상태를 재구성할 수 있음

핵심 구성 요소

  • 이벤트
    • 고유 ID, 생성 시간, 이벤트 타입, 사용자 정보, 내용(body)을 포함하며 불변성과 자기 완결성을 보장
  • 스테이트
    • 모든 이벤트를 재생해 산출한 최종 상태(필요 시 스냅샷이나 캐시 활용)
  • 리듀서
    • 순수 함수로 이전 상태와 이벤트를 입력받아 새로운 상태를 계산하며 불변성을 유지
  • 엔티티
    • 관련 이벤트들을 모아 하나의 객체로 관리하여, 특정 엔티티의 변경 이력을 효율적으로 조회

구현 예시 및 구조

  • 기본 환경 설정: NestJS를 이용해 애플리케이션 구동
  • 엔티티 및 이벤트 정의
    • TypeScript 인터페이스와 MongoDB 스키마를 활용해 다양한 이벤트(예: 설정 생성, 파라미터 추가/삭제)와 상태 객체를 명확히 정의
  • 리듀서 구현:
    • 이벤트 타입별로 상태를 업데이트하는 순수 함수를 작성하여, 이벤트 시퀀스를 재생해 최종 상태 산출
  • API 엔드포인트 및 서비스 레이어
    • 컨피그 생성, 조회, 파라미터 추가/삭제 기능을 제공하는 REST API 구현
    • dispatch-commit 패턴을 활용해 이벤트 발행 후 상태 계산과 이벤트 저장을 순차적으로 처리

추가 고도화 및 외부 시스템 통합

  • 제너릭 인터페이스
    • 재사용 가능한 이벤트 리포지토리 설계로 코드 중복을 줄이고 타입 안전성 확보
  • 이벤트 핸들러
    • Slack 등 외부 시스템과 연동해 이벤트 발생 시 알림 전송 등 추가 처리를 수행
  • 성능 최적화 전략
    • 스냅샷: 특정 시점의 상태를 저장해 이후 이벤트만 적용, 전체 이벤트 재생 비용을 절감
    • 캐싱: 인메모리 캐시나 Redis를 활용해 자주 조회되는 엔티티 상태를 빠르게 제공

결론

  • 이벤트 소싱은 모든 변경 이력을 명확히 기록해 신뢰성과 유지보수성을 높이는 강력한 아키텍처
  • 도메인에 맞는 점진적 도입과 스냅샷, 캐싱 등의 최적화 전략을 병행하여 시스템 성능을 확보하고, 학습 곡선을 고려해 신중하게 도입해야 함