--- title: Debezium Outbox Event Router (공식 문서) source_type: official-doc url: https://debezium.io/documentation/reference/stable/transformations/outbox-event-router.html archive_url: status: raw confidence: medium tags: [ca-outbox-pattern, debezium, cdc, outbox-event-router, kafka-connect, official-doc] related_projects: [ca-skeleton-operational-contract] related_branches: [feature-domain-event-outbox-contract, feature-background-job-async-contract] created: 2026-05-22 last_reviewed: 2026-05-27 --- # Debezium Outbox Event Router (공식 문서) > Layer: `raw/official-docs/` — Debezium 공식 documentation "Outbox Event Router" SMT (Single Message Transform) 의 **원문 발췌·출처 기록**. > ca-tmpl 의 SKIP LOCKED outbox 결정에 대한 **대안 1: CDC 기반 outbox 발행**. Debezium 이 outbox 테이블의 INSERT log 를 읽어 Kafka 로 보내는 모델. ## Parent / 활용 branch (필수) | Branch | 이 자료가 정당화하는 결정 | |---|---| | [[raw/branch-notes/feature-domain-event-outbox-contract]] | Topic 3 — Outbox Pattern 대안 비교 (대안 1: Debezium CDC) 의 1차 근거 — polling 부하 없는 outbox 발행 모델 | | [[raw/branch-notes/feature-background-job-async-contract]] | Background job / async event 발행 인프라 선택 시 polling 대비 CDC 의 trade-off 비교 근거 | | [[raw/project-notes/ca-skeleton-operational-contract]] | §18 (Control Plane Contract) / §19 (Domain Application Readiness Contract) 의 outbox 발행 대안 매트릭스에서 baseline (SKIP LOCKED polling) 의 대조점 | ## 컨텍스트 ca-tmpl 이 채택한 SKIP LOCKED polling 방식의 직접 대안. Debezium 은 DB transaction log (Postgres WAL / MySQL binlog) 를 읽어 outbox 테이블의 INSERT 를 Kafka topic 으로 routing. polling 인스턴스 자체가 사라지고 Kafka Connect cluster 가 그 역할을 대체. ## 출처 / Source - 원본 URL: https://debezium.io/documentation/reference/stable/transformations/outbox-event-router.html - 보조 URL (Debezium 블로그 — Gunnar Morling): https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/ - 아카이브 URL: (미수집) - 저자 / 조직: Debezium project / Red Hat - 발행일: rolling docs (페이지 자체에 명시 없음) - 마지막 확인일 (capture): 2026-05-22 - 마지막 재검증 시도: 2026-05-27 - **[2026-05-25 capture]**: user 가 2026-05-22 수집한 인용 원형 유지 (재검증 보류 마커는 2026-05-25 부여된 상태). - **재검증 결과 [2026-05-27 verified attempt]**: 1차 URL (`https://debezium.io/documentation/reference/stable/transformations/outbox-event-router.html`) WebFetch HTTP 403 Forbidden. 버전 핀(`/3.3/`) 및 보조 URL (Debezium 블로그 2019-02-19) 도 403 — debezium.io 가 WebFetch UA 를 일괄 차단하는 것으로 보임. verbatim 재확인 불가. - **재검증 한계**: 2026-05-27 다중 채널 WebFetch 차단 — 본 인용은 user 가 2026-05-22 수집한 원본 발췌 원형 보존, verbatim 재확인 보류. 본 문서 인용은 모두 `needs-confirmation` Strength 유지 (Strength 상향 없음). ## 핵심 인용 / Key quotes (verbatim, user 수집본 [2026-05-25 capture] — [2026-05-27 verified attempt] WebFetch 403 차단으로 verbatim 재확인 보류) > [§Outbox Event Router SMT] "The outbox event router is a single message transformation (SMT) that takes the events captured from an outbox table and routes them to topics named after the event aggregate type." > [§CDC vs polling] "Capturing changes via the database's transaction log (CDC) avoids the cost of polling the outbox table." > [§Immediate DELETE] "Since Debezium reads the transaction log, the outbox row only needs to exist long enough for the log to be captured; you can immediately DELETE the row in the same transaction." > [§Delivery semantics] "The pattern provides at-least-once delivery semantics. Consumers must therefore be idempotent." ## Claims Extracted / 추출된 주장 > 이 자료가 직접 말하는 것만 claim 으로 분리. 본 raw 의 모든 quote 는 2026-05-22 user 수집본이며 2026-05-27 WebFetch 차단으로 verbatim 재확인 보류 → 전체 `needs-confirmation`. | Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove | |---|---|---|---|---|---| | OUTBOX-DBZ-C1 | Outbox Event Router 는 outbox 테이블에서 캡처된 이벤트를 event aggregate type 이름의 Kafka topic 으로 routing 하는 SMT (Single Message Transformation) | [§Outbox Event Router SMT] "The outbox event router is a single message transformation (SMT) that takes the events captured from an outbox table and routes them to topics named after the event aggregate type." | `needs-confirmation` | Debezium connector + Kafka Connect 환경 | aggregate type 외 partition key / header / payload schema 등 모든 라우팅 정책의 default 동작을 본 인용으로 확정할 수 없음 | | OUTBOX-DBZ-C2 | CDC (DB transaction log 기반 캡처) 는 outbox 테이블을 polling 하는 비용을 회피한다 | [§CDC vs polling] "Capturing changes via the database's transaction log (CDC) avoids the cost of polling the outbox table." | `needs-confirmation` | Postgres logical replication / MySQL row-based binlog 가 활성화된 DB | polling 자체가 모든 DB 부하 시나리오에서 더 비싸다는 일반 명제는 아님 — interval, table size, index, vacuum 조건에 따라 다름 | | OUTBOX-DBZ-C3 | CDC 가 transaction log 를 읽기 때문에 outbox row 는 log capture 가 완료될 만큼만 존재하면 되며, 동일 트랜잭션에서 즉시 DELETE 가능 | [§Immediate DELETE] "Since Debezium reads the transaction log, the outbox row only needs to exist long enough for the log to be captured; you can immediately DELETE the row in the same transaction." | `needs-confirmation` | Debezium + Postgres/MySQL logical/row-based replication | DELETE 직후 connector 장애 시 손실 없음을 보장한다는 뜻은 아님 — connector offset/HA 설계와 결합 필요 | | OUTBOX-DBZ-C4 | Debezium Outbox 패턴은 at-least-once delivery 를 제공하며 consumer 는 idempotent 해야 한다 | [§Delivery semantics] "The pattern provides at-least-once delivery semantics. Consumers must therefore be idempotent." | `needs-confirmation` | Debezium outbox SMT 를 사용하는 end-to-end pipeline | exactly-once 가 일부 Kafka Connect 모드에서 부분적으로 가능하나, outbox SMT 조합의 end-to-end EOS 는 본 인용으로 보장 안 됨 | ### Strength 정책 본 문서의 모든 claim 은 `needs-confirmation`. 이유: 2026-05-27 재검증 시점에 WebFetch 가 차단되어 user 수집본 (2026-05-22) 의 verbatim 일치 여부를 공식 페이지 대조로 확인 못함. wiki 승급 전 재확인 필수. ## Usage Boundaries / 적용 경계 - **이 자료가 직접 증명하는 것** (재확인 시): - `OUTBOX-DBZ-C1`: Debezium Outbox Event Router SMT 의 정의와 routing 기준 (aggregate type) - `OUTBOX-DBZ-C2`: CDC 가 polling 비용을 회피한다는 공식 입장 - `OUTBOX-DBZ-C3`: outbox row 즉시 DELETE 가능 (table hot 방지) - `OUTBOX-DBZ-C4`: at-least-once 보장 + consumer idempotency 필수 - **이 자료가 증명하지 않는 것**: - Kafka Connect cluster HA / offset 관리 / schema evolution 의 실제 운영 비용 - Debezium connector 장애 시 복구 절차의 정확한 SLA - CDC lag 의 정확한 수치 (claim 은 "polling 비용 회피"이지 "ms 단위 lag" 보장이 아님) - end-to-end exactly-once (consumer 측 + Kafka Connect EOS mode 조합 필요, 본 인용으로 미보장) - **내 프로젝트에 적용하려면 추가 확인이 필요한 것**: - ca-tmpl 이 운영하는 Postgres 의 `wal_level=logical` 활성화 여부 + 운영 DBA 정책 - Kafka + Kafka Connect 클러스터 도입 비용 (인력 / 인프라) - aggregate type 기반 routing 이 ca-tmpl 의 domain event taxonomy 와 호환되는지 ## 메모 / Notes (내 프로젝트 해석 — 직접 인용 아님) - 적용 시나리오: 이미 Kafka + Kafka Connect 를 운영 중이거나 도입 가능한 조직. write throughput 이 높아 polling 부하/lag 이 문제가 되는 케이스. - 장점: - **polling 없음** → DB 부하 거의 없음, lag 이 ms 단위 - outbox row 를 즉시 DELETE 가능 (transaction log 에 흔적이 남음) → 테이블이 hot 하지 않음 - aggregate type 기반 자동 라우팅 (`outbox.event.router`) - 순서가 partition 내에서 자연 보장 - 단점: - **Kafka + Kafka Connect + Debezium connector** 인프라 운영 필요 - DB 의 logical replication / binlog 활성화 (Postgres `wal_level=logical`, MySQL row-based binlog) 필요 → DBA 협조 + 운영 부담 - Debezium connector 자체의 HA · offset 관리 · schema evolution 대응 필요 - connector 장애 시 lag 발생, 복구 절차가 polling 보다 복잡 - ca-tmpl (SKIP LOCKED polling) 과의 차이: - polling 인스턴스 자체가 사라지고 Kafka Connect cluster 가 그 역할을 대체 - lag 특성이 "interval 기반"에서 "WAL 따라잡기 기반"으로 바뀜 - 인프라 의존성이 DB-only 에서 **DB + Kafka + Kafka Connect** 로 증가 - 운영 복잡도: 중상. Kafka Connect 운영 경험 필요. - exactly-once / at-least-once 보장 수준: **at-least-once** (`OUTBOX-DBZ-C4`). - 외부 의존성 추가 여부: **Kafka, Kafka Connect, Debezium**. 큼. - 대안 그룹 (Topic 3 — Outbox Pattern, 대안 6종): SKIP LOCKED polling / **Debezium CDC** / Kafka Connect SMT / Dual-write [금지] / Event sourcing / Spring @TransactionalEventListener - 본 source 의 위치: 대안 1 — Debezium CDC ## Related / 관련 - 같은 주제 다른 official-doc: - [[raw/official-docs/outbox-skip-locked-microservices-io]] (baseline: SKIP LOCKED polling) - [[raw/official-docs/skip-locked-postgres-docs]] (Postgres 공식 — SKIP LOCKED 메커니즘) - [[raw/official-docs/dual-write-antipattern-microservices-io]] (negative reference) - 같은 주제 company-tech-blog: - [[raw/company-tech-blogs/outbox-woowahan-techblog-pattern]] - 인용하는 branch / project: - [[raw/branch-notes/feature-domain-event-outbox-contract]] - [[raw/branch-notes/feature-background-job-async-contract]] - [[raw/project-notes/ca-skeleton-operational-contract]] - 인용한 wiki 요약: (미작성)