핵심 인사이트 (3줄 요약)

  1. 본질: 이벤트 소싱(Event Sourcing)은 시스템 상태를 이벤트 스트림으로 저장해 언제든 과거 시점으로 재현(Replay)하는 패턴이다.
  2. 가치: 람다(Lambda)는 배치+스트림 이중 경로로 정확성과 저지연을 동시에 달성하고, 카파(Kappa)는 스트림 단일 경로로 운영 복잡도를 줄인다.
  3. 판단 포인트: 배치 재처리 비용과 운영 복잡도 허용 수준에 따라 람다 vs 카파를 선택하며, 최신 스트림 엔진(Flink, Spark Structured Streaming)은 카파 전환을 가속한다.

Ⅰ. 개요 및 필요성

1.1 이벤트 소싱 (Event Sourcing) 정의

이벤트 소싱은 애플리케이션 상태 변화를 이벤트(Event) 의 연속으로 저장하고, 현재 상태를 이 이벤트들을 순서대로 재적용(Replay)하여 도출하는 패턴이다. 전통적 CRUD 방식이 최종 상태만 저장하는 것과 대비된다.

방식저장 단위특징
CRUD현재 상태(스냅샷)이력 손실, 간단한 구현
이벤트 소싱이벤트 스트림완전한 이력, 재현 가능

1.2 왜 이벤트 소싱이 필요한가?

  • 감사 추적(Audit Trail): 모든 변경 사항이 불변(Immutable) 이벤트로 기록됨
  • 시간 여행(Time Travel): 특정 시점의 상태 재현 가능
  • 새 로직 소급 적용: 비즈니스 로직 변경 시 과거 이벤트 전체 재처리
  • CQRS(Command Query Responsibility Segregation) 와 자연스러운 결합

1.3 이벤트 소싱 이벤트 스트림 개념

시간 흐름 →
┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐
│E1    │→ │E2    │→ │E3    │→ │E4    │→ │E5    │
│주문생성│  │결제완료│  │배송시작│  │배송완료│  │리뷰작성│
└──────┘  └──────┘  └──────┘  └──────┘  └──────┘
     ↓ Replay(재현)
┌─────────────────────────────────┐
│ 현재 상태 = 순서대로 이벤트 적용     │
│ 언제든 원하는 시점 상태 재현 가능    │
└─────────────────────────────────┘

📢 섹션 요약 비유: 이벤트 소싱은 "가계부"와 같다. 잔액만 적어두면 과거를 알 수 없지만, 입출금 내역을 모두 기록하면 어느 날의 잔액이든 계산해낼 수 있다.


Ⅱ. 아키텍처 및 핵심 원리

2.1 람다 아키텍처 (Lambda Architecture)

Nathan Marz가 제안한 빅데이터 처리 아키텍처로, 배치와 스트림 두 레이어를 병렬 운영하여 정확성과 저지연을 동시에 달성한다.

데이터 소스
    │
    ├─────────────────────────────┐
    │                             │
    ▼                             ▼
┌─────────────────┐   ┌─────────────────┐
│  배치 레이어      │   │  스피드 레이어    │
│  (Batch Layer)  │   │  (Speed Layer)  │
│                 │   │                 │
│ HDFS / S3       │   │ Kafka + Flink   │
│ Spark Batch     │   │ 실시간 처리       │
│ 고정확도         │   │ 저지연           │
│ 고지연(시간~일)  │   │ 근사치(최근 데이터)│
└────────┬────────┘   └────────┬────────┘
         │                     │
         ▼                     ▼
┌─────────────────────────────────┐
│          서빙 레이어              │
│         (Serving Layer)         │
│                                 │
│  배치 뷰(Batch View) +           │
│  실시간 뷰(Realtime View) 병합    │
│  → 사용자 쿼리 응답               │
└─────────────────────────────────┘
레이어역할기술 스택지연
Batch Layer전체 데이터 정확 처리HDFS, Spark, Hive시간~일
Speed Layer최근 데이터 빠른 처리Kafka, Flink, Storm초~분
Serving Layer두 레이어 결과 병합 조회Cassandra, Redis, Druidms

2.2 카파 아키텍처 (Kappa Architecture)

Jay Kreps(Kafka 창시자)가 람다의 복잡성을 비판하며 제안. 스트림 처리 단일 레이어로 배치 역할까지 수행.

데이터 소스
    │
    ▼
┌─────────────────────────────────┐
│         메시지 큐(Kafka)          │
│   이벤트 영구 보관 (무한 보존)      │
│   파티셔닝, 순서 보장              │
└────────────────┬────────────────┘
                 │
        ┌────────┴────────┐
        │                 │
        ▼                 ▼
┌──────────────┐  ┌──────────────┐
│ 실시간 처리   │  │ 재처리(Replay) │
│ (Consumer v1)│  │ (Consumer v2) │
│ 현재 로직 적용│  │ 새 로직 소급  │
└──────┬───────┘  └──────┬───────┘
       │                 │
       └────────┬────────┘
                ▼
┌─────────────────────────────────┐
│          서빙 레이어              │
│   단일 스트림 처리 결과 조회        │
└─────────────────────────────────┘

2.3 람다 vs 카파 비교

항목람다 아키텍처카파 아키텍처
처리 경로배치 + 스트림 이중 경로스트림 단일 경로
운영 복잡도높음 (코드 이중화)낮음 (단일 코드베이스)
재처리 방법배치 재실행Kafka 오프셋 리셋 후 재처리
정확도배치 기준 높은 정확도스트림 처리 정확도 (근사 허용)
적합 사례복잡한 집계, ML 학습이벤트 소싱, 실시간 파이프라인
도입 난이도복잡비교적 단순

2.4 CQRS (Command Query Responsibility Segregation)

CQRS는 명령(Command: 쓰기)과 쿼리(Query: 읽기)를 분리하는 패턴이다. 이벤트 소싱과 결합하면 강력한 시스템을 구성한다.

┌─────────────────────────────────────────────────┐
│                   CQRS + 이벤트 소싱              │
│                                                 │
│  클라이언트                                       │
│    │                                            │
│    ├──── Command(쓰기) ──→ Command Handler       │
│    │                           │                │
│    │                           ▼                │
│    │                    이벤트 스토어             │
│    │                    (Kafka/EventStore)       │
│    │                           │                │
│    │                     Projection             │
│    │                    (읽기 모델 생성)          │
│    │                           │                │
│    │                           ▼                │
│    └──── Query(읽기) ──→  Read DB(최적화)        │
│                           (Redis/Elasticsearch) │
└─────────────────────────────────────────────────┘

📢 섹션 요약 비유: 람다는 두 개의 주방에서 요리하는 레스토랑(빠른 패스트푸드 창구 + 정성스러운 정식 주방)이고, 카파는 한 주방에서 빠르고 정확하게 모든 요리를 처리하는 효율적 주방이다.


Ⅲ. 비교 및 연결

3.1 이벤트 소싱 Replay 상세 흐름

[기존 로직 v1 처리 중]
Kafka Topic: order-events (offset 0 ~ 100,000)

오프셋 0  ──→ 이벤트 소비 ──→ 로직 v1 적용 ──→ DB 저장

[새 로직 v2 적용 필요]
          ┌─────────────────────────────────┐
          │  새 컨슈머 그룹(Consumer Group)  │
          │  오프셋 0부터 재시작              │
          │  오프셋 0 ──→ 로직 v2 적용       │
          │  오프셋 1 ──→ 로직 v2 적용       │
          │      ...                        │
          │  오프셋 100,000 ──→ v2 완료      │
          └─────────────────────────────────┘

결과: v2 기준 전체 히스토리 재계산 완료
v1 결과와 병행 운영 후 전환 (Blue/Green)

3.2 Kafka를 이벤트 소싱 스토어로 활용

Kafka 기능이벤트 소싱 활용
토픽(Topic) 파티션엔티티(Entity) ID 기준 파티셔닝
오프셋(Offset)이벤트 순서 보장
보존 기간(Retention)무기한 보존으로 완전한 이력
컨슈머 그룹여러 Projection 병렬 처리
압축(Log Compaction)최신 상태 스냅샷 유지

3.3 이벤트 소싱 vs 전통 DB

비교 항목전통 DB (CRUD)이벤트 소싱
저장 단위현재 상태이벤트 스트림
쿼리 복잡도단순 SELECTProjection 생성 필요
이력 추적별도 감사 테이블 필요기본 제공
확장성수직적 확장수평적 확장
디버깅어려움이벤트 재현으로 용이
스토리지효율적많은 스토리지 필요

📢 섹션 요약 비유: Kafka의 오프셋(Offset)은 책의 페이지 번호와 같다. 어느 페이지부터든 다시 읽을 수 있고, 새 독자(새 컨슈머 그룹)는 1페이지부터 자신만의 읽기를 시작할 수 있다.


Ⅳ. 실무 적용 및 기술사 판단

4.1 람다 vs 카파 선택 기준

상황권장 아키텍처이유
복잡한 집계 쿼리 + 정확도 최우선람다배치 레이어의 정확한 처리
실시간 이벤트 파이프라인카파단순한 운영, 재처리 용이
팀 규모 작음카파이중 코드베이스 유지 부담
레거시 배치 시스템 공존람다점진적 마이그레이션
Flink/Spark Structured Streaming 도입카파배치/스트림 통합 API

4.2 실무 구현 패턴: 이벤트 소싱 + 카파

[주문 시스템 예시]

사용자 주문
    │
    ▼
Order Command Handler
    │ OrderCreated 이벤트 발행
    ▼
Kafka Topic: order-events
 ├─ Partition 0: userId % N
 ├─ 무기한 보존(log.retention.ms=-1)
 └─ Log Compaction 활성화

    │
    ├──→ Consumer Group A: 재고 Projection → Redis
    ├──→ Consumer Group B: 결제 Projection → PostgreSQL
    ├──→ Consumer Group C: 검색 Projection → Elasticsearch
    └──→ Consumer Group D: 분석 Projection → ClickHouse

4.3 재처리(Replay) 운영 절차

  1. 새 Consumer Group 생성: order-events-v2-consumer
  2. 오프셋 초기화: --reset-offsets --to-earliest
  3. 새 로직 컨테이너 배포: Blue/Green 전략으로 병렬 운영
  4. 재처리 완료 검증: 처리 카운트 및 결과 검증
  5. 트래픽 전환: 서빙 레이어에서 v2 결과로 전환
  6. 기존 Consumer 제거: v1 Consumer Group 중단

4.4 주요 도전과 해결책

도전 과제해결 방법
이벤트 스키마 변화Apache Avro + Schema Registry
재처리 시 성능 부하별도 토픽/클러스터에서 재처리
이벤트 순서 보장동일 파티션 키 사용
대용량 이벤트 스토어Kafka Tiered Storage
스냅샷 없이 긴 이력 재현주기적 스냅샷 + 이후 이벤트 적용

📢 섹션 요약 비유: 재처리(Replay)는 비디오 녹화본을 처음부터 다시 돌려보는 것과 같다. 같은 영상이지만 새로운 시각(로직)으로 다시 분석하면 다른 결론을 낼 수 있다.


Ⅴ. 기대효과 및 결론

5.1 이벤트 소싱 + 카파 아키텍처의 기대효과

효과정량적 지표
운영 복잡도 감소람다 대비 코드베이스 50% 감소
재처리 자동화수동 배치 재실행 제거
완전한 감사 추적모든 상태 변화 100% 추적
새 기능 빠른 배포Consumer Group 추가로 무중단 확장

5.2 기술 선택 가이드라인 (기술사 관점)

이벤트 소싱/스트림 아키텍처 의사결정 트리

스트림 처리 필요?
├─ NO  → 전통 CRUD + 배치 ETL
└─ YES → 실시간 정확도 요구?
          ├─ 높음 + 복잡 집계 → 람다 아키텍처
          │   (배치 + 스트림 병렬 운영)
          └─ 보통 + 운영 단순화 → 카파 아키텍처
              (스트림 단일 경로)
              └─ 이력/감사 필요? → 이벤트 소싱 결합

5.3 현업 채택 현황

기업아키텍처용도
Netflix람다 → 카파 전환실시간 추천
LinkedIn카파 (Kafka 기반)사용자 활동 스트림
Uber이벤트 소싱 + CQRS실시간 주문/위치 처리
Airbnb람다 → Flink 기반 카파가격 최적화

5.4 결론 요약

이벤트 소싱은 데이터의 불변성과 재현성을 보장하는 강력한 패턴이며, 카파 아키텍처와 결합 시 운영 단순성과 실시간 처리를 동시에 달성한다. 기술사 시험에서는 람다 vs 카파의 트레이드오프Kafka를 이벤트 소싱 스토어로 활용하는 방법이 핵심 논점이다.

📢 섹션 요약 비유: 이벤트 소싱 + 카파 아키텍처는 "블랙박스 + 실시간 내비게이션" 조합과 같다. 블랙박스(이벤트 스토어)로 모든 주행 기록을 저장하고, 내비게이션(스트림 처리)이 실시간으로 최적 경로를 안내하며, 사고(장애) 시 블랙박스로 정확한 원인을 파악한다.


📌 관련 개념 맵

관계개념설명
저장 패턴Event Sourcing (이벤트 소싱)상태를 이벤트 스트림으로 저장
아키텍처 패턴Lambda Architecture (람다 아키텍처)배치 + 스트림 이중 경로
아키텍처 패턴Kappa Architecture (카파 아키텍처)스트림 단일 경로
설계 패턴CQRS명령과 쿼리 분리
인프라Kafka이벤트 스토어 + 메시지 큐
재처리Replay (재현)오프셋 리셋 후 재처리
표현 변환Projection (프로젝션)이벤트 → 읽기 모델 변환
스키마 관리Schema Registry이벤트 스키마 버전 관리

👶 어린이를 위한 3줄 비유 설명

  1. 이벤트 소싱은 일기를 매일 쓰는 것과 같아요. 일기를 처음부터 다시 읽으면 오늘의 나를 정확히 이해할 수 있죠.

📈 관련 키워드 및 발전 흐름도

CRUD 기반 상태 저장 (현재 상태만 유지)
    │
    ▼
이벤트 소싱 (Event Sourcing): 모든 변화를 이벤트로 기록
    ├─► 이벤트 스토어: 불변 로그 (Kafka · EventStoreDB)
    └─► 상태 재구성: 이벤트 리플레이 (Replay)
    │
    ▼
람다 아키텍처: Batch Layer + Speed Layer 분리
    │
    ▼
카파 아키텍처: Speed Layer만으로 통합 (Kafka 중심)
    │
    ▼
CQRS: 쓰기 모델(Command)과 읽기 모델(Query) 분리
  1. 람다 아키텍처는 두 개의 창구가 있는 은행이에요. 빠른 창구(스트림)와 정확한 창구(배치) 두 곳에서 결과를 합쳐요.
  2. 카파 아키텍처는 스트리밍 서비스처럼 한 곳에서 모든 영상을 보여주는데, 필요하면 처음부터 다시 재생해서 새로운 자막(로직)도 입힐 수 있어요.