--- title: 우아한형제들 — 도메인 이벤트 발행 / Outbox 패턴 적용 사례 source_type: company-tech-blog url: https://techblog.woowahan.com/ archive_url: status: raw confidence: low tags: [ca-outbox-pattern, woowahan, korean-techblog, polling, company-tech-blog] 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 --- # 우아한형제들 — Outbox 패턴 사례 > Layer: `raw/company-tech-blogs/` — 우아한형제들 기술블로그의 outbox 패턴 사례 **원문 발췌·출처 기록**. > ca-tmpl 이 채택한 **DB polling + SKIP LOCKED 방식**과 가장 가까운 한국 사례 후보. 같은 결정을 한 조직이 어떤 trade-off 를 인정하고 갔는지 확인하는 corroboration 자료. ## Parent / 활용 branch (필수) | Branch | 이 자료가 정당화하는 결정 | |---|---| | [[raw/branch-notes/feature-domain-event-outbox-contract]] | Topic 3 — Outbox Pattern baseline (SKIP LOCKED polling) 의 한국 사례 corroboration — 단 인용 wording 미확인 시 corroboration 강도 제한 | | [[raw/branch-notes/feature-background-job-async-contract]] | Background job 발행에서 JPA + Spring Boot + Kafka publisher 조합의 사례 자료 (정확 URL 보강 필요) | | [[raw/project-notes/ca-skeleton-operational-contract]] | §18 / §19 의 outbox 채택 — 한국 production 환경에서 동일 결정을 한 사례 reference | ## 컨텍스트 ca-tmpl 이 채택한 **DB polling + SKIP LOCKED 방식**과 가장 가까운 한국 사례 후보. 같은 결정을 한 조직이 어떤 trade-off 를 인정하고 갔는지 확인. 단, 본 raw 의 인용은 2026-05-22 작성 시점에 정확한 글 URL 을 확정하지 못한 상태로 다수 글의 공통 메시지 요약 형태이며, 2026-05-27 재검증에서도 정확 wording 확인이 불가하여 **company-tech-blog 사례로서의 가치보다 corroboration 한계가 더 크다**. ## 출처 / Source - 원본 URL (블로그 메인): https://techblog.woowahan.com/ - 대상 글 URL: **미확정** — "MSA 환경에서의 이벤트 발행 / 트랜잭션 아웃박스" 류 글 다수에서 반복되는 메시지를 요약한 형태 - 아카이브 URL: (미수집) - 저자 / 조직: 우아한형제들 기술블로그 (Woowahan Tech Blog) - 발행일: 미확인 (글 URL 미확정) - 마지막 확인일 (capture): 2026-05-22 - 마지막 재검증 시도: 2026-05-27 - **[2026-05-25 capture]**: user 가 2026-05-22 수집한 paraphrase 요약 원형 유지. - **재검증 결과 [2026-05-27 verified attempt]**: 블로그 landing page `https://techblog.woowahan.com/` WebFetch 성공. 그러나 landing 에 노출된 최신 featured 글 (RAG chatbot / AI harness / multilingual / React 19 / review LLM / MCP stdio / incident lifecycle) 중 outbox / 도메인 이벤트 발행 / SKIP LOCKED / Kafka publisher / 이벤트 발행 키워드와 직접 매칭되는 글 **없음**. 단일 글 URL 확정 실패 — 카테고리 archive (Backend / Infra) 또는 검색 API 필요. - **재검증 한계 + Strength 정책**: 원본 글 URL 여전히 미확정 → 본 자료는 source_type 을 `company-tech-blog` 로 분류하지만 **단일 글 인용으로 corroborate 불가**. 추출된 모든 claim 은 `needs-confirmation` Strength **유지** (Strength 상향 없음). 본 자료는 ca-tmpl 결정의 official 정당화로 사용 불가 — microservices.io / Postgres 공식이 1차, 본 자료는 단일 글 + verbatim 확보 전까지 보조 corroboration 으로도 사용 보류. - **company-tech-blog evidence 는 official best practice 가 아님**: 본 자료는 official-standard / official-vendor-doc / official-reference 가 아니므로 "우아한형제들이 채택했으므로 best practice" 라는 추론 금지. ## 핵심 인용 / Key quotes (paraphrase / 요약, 2026-05-22 user 수집본 — verbatim 아님) > **주의**: 아래는 verbatim 인용이 아니라 우아한형제들 기술블로그 다수 글에서 반복되는 메시지의 user paraphrase 요약. wiki 승급 전 단일 글 URL + verbatim 확보 필수. > (paraphrase) "단일 트랜잭션 안에서 비즈니스 변경과 이벤트 저장을 묶어 두고, 별도 publisher 가 그 이벤트를 외부로 발행한다." > (paraphrase) "Kafka 에 직접 publish 하지 않는 이유는 dual-write 문제 때문이다." > (paraphrase) "polling 주기와 SKIP LOCKED 기반 다중 publisher 인스턴스로 처리량을 확보한다." ## Claims Extracted / 추출된 주장 > **중요**: 본 raw 는 verbatim 인용이 아니라 paraphrase 요약만 보유. 모든 claim 은 `needs-confirmation`. 단일 글 URL + verbatim 확보 전까지 corroboration 으로 사용 불가. | Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove | |---|---|---|---|---|---| | OUTBOX-WW-C1 | 우아한형제들의 일부 도메인은 단일 트랜잭션에서 비즈니스 변경 + 이벤트 저장 (outbox) 을 묶고 별도 publisher 가 외부 발행하는 패턴을 사용한다 (paraphrase) | (paraphrase) "단일 트랜잭션 안에서 비즈니스 변경과 이벤트 저장을 묶어 두고, 별도 publisher 가 그 이벤트를 외부로 발행한다." | `needs-confirmation` | 우아한형제들 일부 도메인 (정확한 글 / 시스템 범위 미확인) | "우아한형제들 전사 표준" 이라는 일반화는 본 자료로 보장 안 됨 — 단일 글 paraphrase 단계 | | OUTBOX-WW-C2 | Kafka 직접 publish 를 피한 이유로 dual-write 문제를 언급 (paraphrase) | (paraphrase) "Kafka 에 직접 publish 하지 않는 이유는 dual-write 문제 때문이다." | `needs-confirmation` | outbox 도입 결정 논리 | dual-write 문제의 정의 / 실제 incident 가 있었는지 본 paraphrase 에 없음 — 일반적 reasoning 으로 추정 | | OUTBOX-WW-C3 | polling interval + SKIP LOCKED 기반 다중 publisher 인스턴스로 처리량을 확보 (paraphrase) | (paraphrase) "polling 주기와 SKIP LOCKED 기반 다중 publisher 인스턴스로 처리량을 확보한다." | `needs-confirmation` | polling Message Relay 변형 | 정확한 interval / 인스턴스 수 / TPS 수치는 본 paraphrase 에 없음 | ### Strength 정책 본 문서의 모든 claim 은 `needs-confirmation`. 추가로 다음 두 제약: 1. verbatim 인용이 아닌 paraphrase → corroboration 강도가 일반 company-case-study 보다 약함 2. 단일 글 URL 미확정 → "우아한형제들이 X 라고 말했다" 라는 단정 자체가 불가, "다수 글의 공통 메시지로 보인다" 수준의 약한 진술만 가능 **company-tech-blog evidence 는 official best practice 가 아님** — 본 자료는 ca-tmpl 의 SKIP LOCKED polling 채택을 official 로 정당화하지 않으며, microservices.io / Postgres 공식 등 official-vendor-doc 으로 별도 정당화 필요. ## Usage Boundaries / 적용 경계 - **이 자료가 직접 증명하는 것** (단일 글 URL + verbatim 확보 시): - 한국 production 환경의 일부 조직이 SKIP LOCKED polling 패턴을 채택한 사례가 존재한다는 약한 corroboration - **이 자료가 증명하지 않는 것**: - "우아한형제들 전사 표준" 또는 "한국 fintech / commerce 일반 표준" 같은 일반화 - 정확한 polling interval / 인스턴스 수 / TPS / lag 수치 - 우아한형제들이 dual-write 문제를 실제 incident 로 겪었는지 (이론적 reasoning vs 운영 경험 구분 불가) - SKIP LOCKED polling 이 best practice 라는 명제 (company-tech-blog 는 official best practice 가 아님) - **내 프로젝트에 적용하려면 추가 확인이 필요한 것**: - 본 raw 를 corroboration 으로 활용하려면 **단일 글 URL + verbatim 인용 확보** 가 선행 — 현 상태로는 wiki 승급 불가 - corroboration 이 확보되더라도 official 정당화는 microservices.io / Postgres 공식 자료가 1차, 본 자료는 한국 사례 보조 ## 메모 / Notes (내 프로젝트 해석 — 직접 인용 아님) - 적용 시나리오 (사례 가설): Kafka 도입은 했으나 Debezium / Kafka Connect 까지는 운영하지 않는 조직. JPA / Spring Boot 기반 도메인이 많은 환경. - 장점 (한국 기술블로그들이 공통적으로 강조 — paraphrase): - 기존 RDB + JPA 스택 그대로 활용 - 운영 인력이 SQL 로 outbox 상태를 직접 진단 가능 (장애 시 큰 이점) - Kafka Connect 운영 부담 없음 - 단점: - polling lag (보통 수백 ms ~ 수 s — 사례 미검증 추정) - outbox 테이블 hot row 관리 (archive, partition, vacuum) - publisher 인스턴스 장애 시 lag 가시화 필요 - ca-tmpl (SKIP LOCKED polling) 과의 차이: **사실상 동일 패턴 추정**. ca-tmpl 이 같은 진영의 결정을 따르고 있다는 약한 corroboration (verbatim 확보 시). - 운영 복잡도: 낮음~중간. - exactly-once / at-least-once 보장 수준: at-least-once. consumer 측 idempotency 필수. - 외부 의존성 추가 여부: Kafka (broker) 만. Kafka Connect / Debezium 불필요. - 주의: 본 raw 는 인용 wording 이 paraphrase / `needs-confirmation` 이므로, `/ingest` 전에 실제 글 URL 1-2개를 찾아 verbatim 으로 보강 필요. - 대안 그룹 (Topic 3 — Outbox Pattern, 대안 6종): **SKIP LOCKED polling** / Debezium CDC / Kafka Connect SMT / Dual-write [금지] / Event sourcing / Spring @TransactionalEventListener - 본 source 의 위치: ca-tmpl baseline 사례 후보 — 우아한형제들 polling (단, verbatim 미확보로 약한 corroboration) ## Related / 관련 - 같은 주제 official-doc (이쪽이 1차 근거): - [[raw/official-docs/outbox-skip-locked-microservices-io]] (baseline 정의) - [[raw/official-docs/skip-locked-postgres-docs]] (메커니즘) - [[raw/official-docs/outbox-debezium-official-docs]] (대안: CDC) - [[raw/official-docs/dual-write-antipattern-microservices-io]] (negative reference) - 인용하는 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 요약: (미작성)