본문 바로가기
Backend2026년 8월 18일5분 읽기

CDC(변경 데이터 캡처) — DB 변경을 실시간 스트림으로 흘려보내기

YS
김영삼
조회 6
CDC(변경 데이터 캡처) — DB 변경을 실시간 스트림으로 흘려보내기

CDC(Change Data Capture, 변경 데이터 캡처)는 데이터베이스에 일어난 삽입·수정·삭제를 실시간에 가깝게 감지해, 다른 시스템으로 스트림처럼 흘려보내는 기법입니다. 애플리케이션 코드를 건드리지 않고, DB가 남기는 트랜잭션 로그를 읽어 변경 이벤트를 뽑아낸다는 게 핵심입니다.

왜 필요할까요. 주문 DB의 변경을 검색엔진, 캐시, 데이터웨어하우스, 추천 시스템에 실시간으로 반영해야 한다고 해봅시다. 애플리케이션에서 매번 "DB 쓰고 → 검색엔진 쓰고 → 캐시 쓰고"를 이중·삼중으로 호출하면, 어느 하나가 실패했을 때 데이터가 어긋납니다(이중 쓰기 문제, dual write). CDC는 "DB에 한 번만 쓰면, 나머지는 로그를 보고 알아서 따라오게" 만들어 이 문제를 우회합니다.

변경을 잡는 두 가지 길

CDC 구현은 크게 폴링 방식과 로그 기반 방식으로 나뉩니다. 이 둘의 차이를 모르고 시작하면 나중에 크게 고생합니다.

항목쿼리/타임스탬프 폴링로그 기반 CDC
방식updated_at 주기적 조회WAL/binlog 구독
삭제 감지어려움(행이 사라짐)가능
DB 부하폴링 쿼리 부담낮음(로그만 읽음)
지연폴링 주기만큼거의 실시간
중간 변경놓칠 수 있음모두 포착

폴링은 구현이 쉬워서 처음엔 끌립니다. 하지만 삭제를 못 잡고, 한 주기 안에 여러 번 바뀐 값의 중간 상태를 놓치며, DB에 부하를 줍니다. 제대로 하려면 결국 로그 기반으로 갑니다.

트랜잭션 로그를 읽는다는 것

모든 관계형 DB는 내구성을 위해 커밋 전에 변경을 로그에 먼저 씁니다. PostgreSQL은 WAL(Write-Ahead Log), MySQL은 binlog가 그것이죠. CDC 도구는 이 로그를 복제 슬레이브인 척 구독합니다. DB 입장에선 그냥 복제본 하나가 붙은 것처럼 보이니 부하가 낮고, 로그엔 커밋된 모든 변경이 순서대로 담겨 있으니 하나도 놓치지 않습니다.

가장 널리 쓰이는 오픈소스가 Debezium입니다. Kafka Connect 위에서 PostgreSQL, MySQL, MongoDB, SQL Server 등의 로그를 읽어 Kafka 토픽으로 변경 이벤트를 흘려보냅니다. 이벤트 하나는 대략 이런 모양입니다.

{
  "op": "u",                    // c=삽입, u=수정, d=삭제
  "before": { "id": 42, "status": "PAID" },
  "after":  { "id": 42, "status": "SHIPPED" },
  "source": { "lsn": 249038, "table": "orders", "ts_ms": 1690000000 }
}

아웃박스 패턴과 함께 쓰면 강해진다

CDC는 종종 트랜잭셔널 아웃박스(outbox) 패턴과 짝을 이룹니다. 비즈니스 데이터와 "발행할 이벤트"를 같은 트랜잭션 안에서 outbox 테이블에 함께 쓰고, CDC가 그 outbox 테이블의 변경만 잡아 메시지 브로커로 내보내는 방식입니다. 이렇게 하면 "DB 커밋"과 "이벤트 발행"이 한 트랜잭션으로 묶여, 둘 중 하나만 성공하는 일이 사라집니다. 이중 쓰기 문제의 정석 해법이죠.

CDC의 진짜 가치는 속도보다 "정합성"에 있습니다. 애플리케이션이 여러 시스템에 직접 쓰는 대신, 단일 진실 원천(DB)의 로그를 따라가게 만들어 데이터 불일치의 뿌리를 없앱니다.

도입 전 반드시 챙길 것

  • 이벤트는 최소 한 번(at-least-once) 전달이 기본입니다. 장애 복구 시 같은 변경이 재전송될 수 있으니, 소비자는 반드시 멱등(idempotent)하게 만드세요.
  • 스키마 변경이 골칫거리입니다. 컬럼이 추가·삭제되면 다운스트림이 깨질 수 있어, 스키마 레지스트리와 호환 정책을 함께 둡니다.
  • 초기 스냅샷이 필요합니다. 로그는 구독 시점 이후만 담기니, 기존 데이터는 별도 스냅샷으로 한 번 실어와야 전체 상태가 맞습니다.
  • 로그 보존 기간을 넉넉히. 소비자가 오래 멈췄다 깨어났을 때 필요한 로그가 이미 삭제됐으면 재동기화 지옥이 열립니다.

자주 묻는 질문

CDC와 그냥 메시지 큐로 이벤트 발행하는 건 뭐가 다른가요?

애플리케이션이 큐에 직접 발행하면 "DB 쓰기 성공, 큐 발행 실패" 같은 불일치가 생깁니다. CDC는 DB 커밋 자체를 이벤트 원천으로 삼아, 커밋된 변경은 반드시 전달되고 커밋 안 된 건 절대 안 나가도록 보장합니다.

NoSQL도 CDC가 되나요?

됩니다. MongoDB는 change stream(oplog 기반), DynamoDB는 Streams라는 이름으로 자체 CDC를 제공합니다. Debezium도 MongoDB를 지원합니다.

지연은 얼마나 되나요?

로그 기반은 보통 수십~수백 밀리초 수준입니다. 다만 브로커 적재, 소비자 처리까지 합친 종단 지연은 파이프라인 구성에 따라 달라지니 실측이 필요합니다.

이벤트 순서는 보장되나요?

같은 키(예: 같은 주문 id) 내에서는 로그 순서가 유지되도록 파티셔닝하는 게 보통입니다. 서로 다른 키 사이의 전역 순서까지는 일반적으로 보장하지 않으니, 순서에 의존하는 로직은 키 단위로 설계하세요.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록