CDC와 Outbox Pattern
3줄 요약
CDC와 Outbox Pattern 챕터는 업무 DB 변경과 이벤트 발행을 동시에 맞추기 어려운 dual write 문제를 outbox table, CDC, publisher, idempotent consumer로 줄이는 방법을 다룬다.
- 핵심은 DB transaction 안에는 사실 기록을 남기고, transaction 밖의 발행 지연과 중복은 관측, 재시도, 재처리 가능한 상태로 관리하는 것이다.
- Java/Spring 백엔드 개발자는
@Transactional 경계, outbox schema, Debezium connector, Kafka publish, consumer 멱등성, cleanup 정책을 하나의 운영 흐름으로 설명해야 한다.
핵심 정리
Dual Write 문제: DB 저장과 Kafka 발행을 별도 작업으로 처리하면 DB만 성공하거나 발행만 성공하는 순간 downstream 데이터가 틀어진다.
Transactional Outbox Pattern: 업무 변경과 outbox insert를 같은 DB transaction에 넣고, 발행은 나중에 publisher나 CDC가 맡아 복구 가능성을 만든다.
CDC Debezium 기본: Debezium은 WAL/binlog 같은 DB commit log를 읽어 변경 이벤트를 만든다. snapshot, offset, schema 변경, connector lag를 함께 관리해야 한다.
Exactly-once 환상과 At-least-once 현실: end-to-end exactly-once는 대부분 성립하지 않는다. outbox와 CDC도 consumer 멱등성 없이는 중복 side effect를 막지 못한다.
Outbox 운영과 정리 전략: outbox는 운영 DB에 남는 table이므로 pending, published, failed, cleanup lag, 보관 기간을 명확히 관리해야 한다.
- 이 챕터는 Web-Database의 transaction 내부 정합성을 넘어, commit 이후 변경 사실이 다른 시스템으로 전달되는 신뢰성을 다룬다.
헷갈리는 지점
@Transactional 안에서 DB 저장과 Kafka 발행을 함께 호출하면 원자적이라고 착각하기 쉽다.
- DB transaction과 Kafka publish transaction은 기본적으로 하나의 commit 단위가 아니다.
- 장애 순간에는 DB row는 있는데 event가 없거나, event는 있는데 DB row가 rollback된 상태가 생길 수 있다.
- outbox는 메시지 발행을 즉시 보장하는 기술이 아니다.
- outbox는 발행할 사실을 DB에 남겨 나중에 복구할 수 있게 하는 패턴이다.
- 따라서 pending count, oldest pending age, publisher error를 반드시 봐야 한다.
- 이 구분이 흐리면 API 성공과 downstream 반영 성공을 같은 사건으로 오해한다.
- CDC를 붙이면 모든 정합성 문제가 사라진다고 보기 쉽다.
- CDC는 commit log를 읽는 전달 경로일 뿐이며, connector lag, snapshot, schema change, duplicate delivery는 여전히 설계 대상이다.
확인 질문
- 이 챕터의 핵심 판단 기준은 무엇인가?
- business row 변경과 event 기록이 같은 DB transaction에 묶이고, 발행 지연과 중복을 outbox 상태, CDC offset, consumer dedup key로 추적할 수 있는지다.
- Web-Database와의 경계는 무엇인가?
- Web-Database는 DB transaction 자체의 정합성과 query 성능을 다루고, 이 챕터는 commit된 변경을 외부 stream으로 안전하게 전달하는 문제를 다룬다.
- 개인 프로젝트에서 최소로 챙길 것은 무엇인가?
- outbox table,
@Transactional 저장 예시, publisher 또는 CDC 대체 scheduler, pending/failed 조회, 같은 event 재전달 테스트다.