[Daily morning study] CDC (Change Data Capture) 개념과 활용

#daily morning study

Image


CDC란 무엇인가

CDC(Change Data Capture)는 데이터베이스에서 발생하는 변경 사항(INSERT, UPDATE, DELETE)을 실시간으로 감지하고 캡처하는 기법이다. 원본 DB의 변경 이벤트를 다른 시스템(데이터 웨어하우스, 캐시, 검색 엔진, 메시지 큐 등)으로 전파하는 데 주로 사용한다.

전통적인 배치 방식(주기적 풀링)과의 가장 큰 차이는 지연시간(latency)이다. 배치는 분~시간 단위 지연이 생기지만, CDC는 밀리초~초 단위 수준의 거의 실시간 복제가 가능하다.


CDC의 주요 방식

1. 로그 기반 CDC (Log-based CDC)

가장 일반적으로 쓰이는 방식이다. 데이터베이스가 내부적으로 유지하는 트랜잭션 로그(WAL, binlog, redo log)를 읽어 변경 사항을 추출한다.

DB로그 이름
PostgreSQLWAL (Write-Ahead Log)
MySQLbinlog (Binary Log)
OracleRedo Log
MongoDBOplog

장점

  • 원본 DB 성능에 거의 영향 없음 (로그는 어차피 생성됨)
  • 트랜잭션 순서 보장
  • DELETE 이벤트도 캡처 가능

단점

  • DB별로 로그 포맷이 다름 → 구현 복잡도 증가
  • 로그 보존 기간 설정 필요 (로그가 지워지면 복구 불가)

2. 트리거 기반 CDC (Trigger-based CDC)

DB 트리거를 이용해 변경 발생 시 별도의 이력 테이블에 레코드를 기록하는 방식이다.

CREATE TABLE orders_cdc (
    id SERIAL PRIMARY KEY,
    operation CHAR(1),  -- 'I', 'U', 'D'
    changed_at TIMESTAMP DEFAULT NOW(),
    old_data JSONB,
    new_data JSONB
);

CREATE OR REPLACE FUNCTION capture_orders_changes()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'DELETE' THEN
        INSERT INTO orders_cdc(operation, old_data)
        VALUES ('D', row_to_json(OLD));
    ELSIF TG_OP = 'INSERT' THEN
        INSERT INTO orders_cdc(operation, new_data)
        VALUES ('I', row_to_json(NEW));
    ELSE
        INSERT INTO orders_cdc(operation, old_data, new_data)
        VALUES ('U', row_to_json(OLD), row_to_json(NEW));
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER orders_cdc_trigger
AFTER INSERT OR UPDATE OR DELETE ON orders
FOR EACH ROW EXECUTE FUNCTION capture_orders_changes();

장점

  • DB 표준 기능만으로 구현 가능
  • 특정 컬럼 변경만 필터링하기 쉬움

단점

  • 모든 DML 작업마다 트리거가 실행 → 원본 DB 부하 증가
  • 대량 배치 작업(bulk load) 시 심각한 성능 저하
  • 이력 테이블 관리 비용 발생

3. 쿼리 기반 CDC (Query-based / Timestamp-based CDC)

변경 추적용 컬럼(updated_at, version 등)을 두고 주기적으로 쿼리해 변경 레코드를 찾는 방식이다.

-- 마지막 체크 이후 변경된 레코드 조회
SELECT *
FROM orders
WHERE updated_at > :last_checked_at
ORDER BY updated_at;

장점

  • 구현이 단순
  • 특별한 DB 권한 불필요

단점

  • DELETE 이벤트 캡처 불가 (레코드가 사라지면 알 수 없음)
  • 변경 감지에 최소 1 폴링 주기만큼 지연 발생
  • updated_at 컬럼이 없거나 업데이트 안 되는 경우 누락 가능

CDC 주요 도구

Debezium

가장 널리 쓰이는 오픈소스 CDC 플랫폼이다. Kafka Connect 위에서 동작하며 다양한 DB 커넥터를 제공한다.

[PostgreSQL WAL]
    ↓
[Debezium PostgreSQL Connector]
    ↓
[Apache Kafka Topic]
    ↓
[Consumer (Elasticsearch, Redis, DW, etc.)]

PostgreSQL의 경우 논리적 복제(logical replication)를 활성화해야 한다.

-- postgresql.conf
wal_level = logical

-- 복제 슬롯 생성 (Debezium이 자동 생성하기도 함)
SELECT pg_create_logical_replication_slot('debezium_slot', 'pgoutput');

Debezium이 캡처하는 이벤트 메시지 예시:

{
  "op": "u",
  "before": {
    "id": 101,
    "status": "PENDING",
    "amount": 5000
  },
  "after": {
    "id": 101,
    "status": "SHIPPED",
    "amount": 5000
  },
  "source": {
    "ts_ms": 1727654400000,
    "db": "shop",
    "table": "orders",
    "lsn": 12345678
  }
}

op 값: c(create), u(update), d(delete), r(read/snapshot)


AWS DMS (Database Migration Service)

AWS에서 제공하는 관리형 데이터 마이그레이션 및 CDC 서비스다. 지속적 복제(Continuous Replication) 모드로 운영하면 CDC처럼 사용할 수 있다.

[Source DB (RDS, on-premise)]
    ↓
[AWS DMS Replication Instance]
    ↓
[Target (S3, Kinesis, Redshift, etc.)]

CDC 활용 사례

1. 검색 엔진 동기화

DB 변경 사항을 Elasticsearch에 실시간 반영한다.

PostgreSQL → Debezium → Kafka → Kafka Connect ES Sink → Elasticsearch

DB가 원천(source of truth)이 되고, Elasticsearch는 검색 최적화된 복제본 역할을 한다.


2. 캐시 무효화 (Cache Invalidation)

DB 레코드가 변경될 때 Redis 캐시를 자동으로 삭제하거나 갱신한다.

[Order UPDATE] → [CDC Event] → [Consumer]
                                    ↓
                              redis.del("order:101")

애플리케이션 코드에서 캐시 갱신 로직을 분리할 수 있어 코드가 단순해진다.


3. 이벤트 소싱 / 감사 로그

모든 데이터 변경 이력을 별도 저장소에 영구 보관한다. 금융, 의료 등 규제가 엄격한 도메인에서 감사 목적으로 많이 쓰인다.


4. 데이터 웨어하우스 적재

운영 DB에서 발생한 변경을 실시간으로 DW(Redshift, BigQuery, Snowflake)에 적재해 분석 지연을 줄인다.


CDC 설계 시 주의점

스키마 변경 처리

원본 테이블에 컬럼이 추가/삭제되면 CDC 파이프라인이 깨질 수 있다. Debezium은 스키마 레지스트리(Confluent Schema Registry 등)와 연동해 이 문제를 관리한다.

초기 스냅샷 (Initial Snapshot)

CDC를 처음 구성할 때는 기존 데이터를 한 번 전체 복사(snapshot)한 뒤 이후 변경 이벤트를 이어받아야 한다. Debezium은 snapshot.mode 설정으로 이를 제어한다.

이벤트 중복 처리 (At-least-once)

CDC 시스템은 일반적으로 at-least-once 전달을 보장한다. 컨슈머가 멱등하게 처리(upsert 등)하도록 설계해야 한다.

복제 슬롯 관리 (PostgreSQL)

PostgreSQL의 논리 복제 슬롯은 소비되지 않은 WAL을 보관하므로, 컨슈머가 오래 멈추면 디스크가 차버릴 수 있다. 모니터링과 슬롯 삭제 정책이 필요하다.

-- 복제 슬롯 상태 확인
SELECT slot_name, active, restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots;

정리

방식원본 부하DELETE 캡처지연복잡도
로그 기반낮음가능매우 낮음높음
트리거 기반높음가능낮음중간
쿼리 기반중간불가폴링 주기낮음

실시간 데이터 파이프라인이 필요하고 원본 DB 부하를 최소화하고 싶다면 로그 기반 CDC + Debezium + Kafka 조합이 사실상 표준이 되고 있다.