서비스 간 이벤트 전파
“주문이 생성됐다”를 쓰면 알림·정산·통계가 각자 구독한다. 마이크로서비스 통합의 기본 형태이고, 이 덱의 주 시나리오다.
서비스끼리 직접 부르면 되는데 왜 하나를 더 세우는가 — 이 질문에 답할 수 있어야 설계가 보인다
결합Coupling백프레셔BackpressureCDCChange Data Capture메시지 큐Message Queue중개자 없이도 서비스는 연동할 수 있다. REST로 서로 부르거나, 같은 DB를 바라보면 된다. 실제로 서비스가 두세 개일 때는 그게 제일 단순하고 옳다. 서비스와 연동처가 늘면서 다음이 전부 아프기 시작한다.
| 통증 | 왜 아픈가 |
|---|---|
| 둘 다 살아 있어야 한다 | 알림 서비스가 죽어 있으면 주문 서비스가 재시도·타임아웃을 떠안는다. 하류 장애가 상류 장애가 되는 구조다 |
| 폭주가 전염된다 | 이벤트가 몰릴 때 받는 쪽 처리 속도가 한계가 되고, 백프레셔가 호출자까지 거슬러 온다 |
| 그 순간 못 받으면 끝 | 호출은 이력이 없다. 받는 쪽이 놓친 이벤트를 나중에 다시 달라고 할 방법이 없다 |
| 연동이 N×M으로 는다 | 소비자가 하나 늘 때마다 생산자 코드를 고쳐 호출을 추가해야 한다 |
| 재시도·순서를 각자 구현한다 | 유실 방지 로직(재시도 큐, 아웃박스…)이 서비스마다 다르게, 대부분 불완전하게 들어간다 |
| DB 공유는 더 나쁘다 | 스키마가 사실상 공용 API가 되어, 테이블 하나 못 바꾸는 조직이 된다 |
호출 대신 기록한다. 생산자는 “무슨 일이 일어났다”를 가운데 로그(Kafka)에 쓰고 끝낸다. 소비자는 로그에서 각자의 속도로 당겨 읽는다. 생산자는 소비자가 몇인지, 살아 있는지, 얼마나 느린지 몰라도 된다 — 결합을 시간 축에서 끊는 것, 이것이 Kafka를 놓는 목적이다.
| 통증 | 로그가 이렇게 푼다 |
|---|---|
| 둘 다 살아 있어야 | 소비자가 죽어도 생산자는 계속 쓴다. 소비자는 살아나서 밀린 곳부터 읽는다 |
| 폭주 전염 | 로그가 완충 장치다. 몰린 만큼 쌓이고, 소비자는 제 속도로 소화한다 |
| 놓치면 끝 | 보존 기간 안에는 다시 읽을 수 있다 — 버그 수정 후 재처리도 가능하다 (2장) |
| N×M 연동 | 생산자는 토픽에 한 번만 쓴다. 소비자 추가는 생산자와 무관하다 |
| 각자 구현 | 유실·중복·순서 보장이 플랫폼 설정으로 내려온다 (6장) |
| DB 공유 | 공유하는 것이 테이블이 아니라 명시적 이벤트 계약(스키마)이 된다 (7장) |
서비스 간 이벤트 전파
“주문이 생성됐다”를 쓰면 알림·정산·통계가 각자 구독한다. 마이크로서비스 통합의 기본 형태이고, 이 덱의 주 시나리오다.
부하 흡수 버퍼
트래픽 폭주를 로그에 받아 두고 소비자가 제 속도로 처리한다. 이메일 발송 · 이미지 처리 같은 비동기 작업 큐 역할.
데이터 파이프라인
로그 · 메트릭 수집, CDC로 DB 변경분을 검색 인덱스 · 캐시 · 분석계로 흘려보내기. Kafka Connect가 이 자리를 맡는다(8장).
스트림 처리
흐르는 데이터를 실시간 집계 · 변환 (Kafka Streams · Flink). 이 덱에서는 존재와 용도만 다룬다(8장).
비교는 같은 층 안에서만 성립한다 — “Kafka vs REST”는 층이 다른 비교다.
| 층 | 물건 | 비고 |
|---|---|---|
| 이벤트 스트리밍 (로그) | Kafka, Redpanda, Pulsar | Redpanda는 Kafka 프로토콜 호환 재구현(C++ · 단일 바이너리). Pulsar는 저장·서빙 분리 구조 |
| 메시지 큐 | RabbitMQ, ActiveMQ | 꺼내면 지운다. 작업 분배·복잡한 라우팅에 강하다 |
| 경량 스트림 | Redis Streams, NATS JetStream | 운영 부담이 작다. 규모·보존 요구가 작으면 충분할 수 있다 |
| 관리형 | Confluent Cloud, AWS MSK | 온프렘 제약이 있으면 선택지에서 빠진다 |
가장 자주 받는 질문이라 따로 짚는다. 본질 차이는 하나 — 읽으면 지우는가, 남는가.
| 메시지 큐 (RabbitMQ류) | Kafka (로그) | |
|---|---|---|
| 읽은 뒤 | 지운다 (ack 기반) | 남는다 — 보존 기간이 지날 때만 지운다 |
| 여러 소비자 그룹 | 팬아웃 익스체인지를 따로 구성 | 기본 동작 — 그룹마다 독립 오프셋 |
| 재처리 | 불가 (이미 지워짐) | 오프셋을 되감으면 된다 |
| 순서 | 큐 단위, 소비자가 늘면 흐려진다 | 파티션 단위로 명확 |
| 개별 메시지 라우팅·우선순위·지연 전송 | 강하다 | 약하다 — 브로커가 단순한 대신 처리량을 얻는다 |