콘텐츠로 이동
Study NoteKafka

1. 왜 Kafka인가

서비스끼리 직접 부르면 되는데 왜 하나를 더 세우는가 — 이 질문에 답할 수 있어야 설계가 보인다

이 장에서 처음 나오는 말4개
결합Coupling
한쪽의 사정(장애 · 배포 · 속도)이 다른 쪽에 그대로 전염되는 정도. 이 장의 통증은 전부 결합의 다른 이름이다.
백프레셔Backpressure
하류(받는 쪽)가 느릴 때 그 압력이 상류(보내는 쪽)로 거슬러 올라오는 현상. 완충 장치가 없으면 하류 장애가 상류 장애가 된다.
CDCChange Data Capture
DB의 변경 내역(INSERT · UPDATE · DELETE)을 로그로 뽑아내 다른 시스템에 흘려보내는 기법. Kafka의 대표 사용처 중 하나다(8장).
메시지 큐Message Queue
RabbitMQ류의 전통적 중개자. 메시지를 꺼내면 지운다 — Kafka와 무엇이 다른지가 이 장의 후반부다.

문제 — 서비스끼리 직접 연동하면

섹션 제목: “문제 — 서비스끼리 직접 연동하면”

중개자 없이도 서비스는 연동할 수 있다. REST로 서로 부르거나, 같은 DB를 바라보면 된다. 실제로 서비스가 두세 개일 때는 그게 제일 단순하고 옳다. 서비스와 연동처가 늘면서 다음이 전부 아프기 시작한다.

가운데 로그가 없을 때 생산자 셋과 소비자 셋이 서로 직접 연결되어 선이 얽히는 모습
통증왜 아픈가
둘 다 살아 있어야 한다알림 서비스가 죽어 있으면 주문 서비스가 재시도·타임아웃을 떠안는다. 하류 장애가 상류 장애가 되는 구조다
폭주가 전염된다이벤트가 몰릴 때 받는 쪽 처리 속도가 한계가 되고, 백프레셔가 호출자까지 거슬러 온다
그 순간 못 받으면 끝호출은 이력이 없다. 받는 쪽이 놓친 이벤트를 나중에 다시 달라고 할 방법이 없다
연동이 N×M으로 는다소비자가 하나 늘 때마다 생산자 코드를 고쳐 호출을 추가해야 한다
재시도·순서를 각자 구현한다유실 방지 로직(재시도 큐, 아웃박스…)이 서비스마다 다르게, 대부분 불완전하게 들어간다
DB 공유는 더 나쁘다스키마가 사실상 공용 API가 되어, 테이블 하나 못 바꾸는 조직이 된다

해법 — 가운데에 로그를 놓는다

섹션 제목: “해법 — 가운데에 로그를 놓는다”

호출 대신 기록한다. 생산자는 “무슨 일이 일어났다”를 가운데 로그(Kafka)에 쓰고 끝낸다. 소비자는 로그에서 각자의 속도로 당겨 읽는다. 생산자는 소비자가 몇인지, 살아 있는지, 얼마나 느린지 몰라도 된다 — 결합을 시간 축에서 끊는 것, 이것이 Kafka를 놓는 목적이다.

가운데에 Kafka 로그를 두면 생산자와 소비자가 각각 로그 한 곳만 보고, 새 소비자를 생산자 수정 없이 붙일 수 있는 모습
통증로그가 이렇게 푼다
둘 다 살아 있어야소비자가 죽어도 생산자는 계속 쓴다. 소비자는 살아나서 밀린 곳부터 읽는다
폭주 전염로그가 완충 장치다. 몰린 만큼 쌓이고, 소비자는 제 속도로 소화한다
놓치면 끝보존 기간 안에는 다시 읽을 수 있다 — 버그 수정 후 재처리도 가능하다 (2장)
N×M 연동생산자는 토픽에 한 번만 쓴다. 소비자 추가는 생산자와 무관하다
각자 구현유실·중복·순서 보장이 플랫폼 설정으로 내려온다 (6장)
DB 공유공유하는 것이 테이블이 아니라 명시적 이벤트 계약(스키마)이 된다 (7장)

서비스 간 이벤트 전파

“주문이 생성됐다”를 쓰면 알림·정산·통계가 각자 구독한다. 마이크로서비스 통합의 기본 형태이고, 이 덱의 주 시나리오다.

부하 흡수 버퍼

트래픽 폭주를 로그에 받아 두고 소비자가 제 속도로 처리한다. 이메일 발송 · 이미지 처리 같은 비동기 작업 큐 역할.

데이터 파이프라인

로그 · 메트릭 수집, CDC로 DB 변경분을 검색 인덱스 · 캐시 · 분석계로 흘려보내기. Kafka Connect가 이 자리를 맡는다(8장).

스트림 처리

흐르는 데이터를 실시간 집계 · 변환 (Kafka Streams · Flink). 이 덱에서는 존재와 용도만 다룬다(8장).

비교는 같은 층 안에서만 성립한다 — “Kafka vs REST”는 층이 다른 비교다.

층물건비고
이벤트 스트리밍 (로그)Kafka, Redpanda, PulsarRedpanda는 Kafka 프로토콜 호환 재구현(C++ · 단일 바이너리). Pulsar는 저장·서빙 분리 구조
메시지 큐RabbitMQ, ActiveMQ꺼내면 지운다. 작업 분배·복잡한 라우팅에 강하다
경량 스트림Redis Streams, NATS JetStream운영 부담이 작다. 규모·보존 요구가 작으면 충분할 수 있다
관리형Confluent Cloud, AWS MSK온프렘 제약이 있으면 선택지에서 빠진다

가장 자주 받는 질문이라 따로 짚는다. 본질 차이는 하나 — 읽으면 지우는가, 남는가.

메시지 큐 (RabbitMQ류)Kafka (로그)
읽은 뒤지운다 (ack 기반)남는다 — 보존 기간이 지날 때만 지운다
여러 소비자 그룹팬아웃 익스체인지를 따로 구성기본 동작 — 그룹마다 독립 오프셋
재처리불가 (이미 지워짐)오프셋을 되감으면 된다
순서큐 단위, 소비자가 늘면 흐려진다파티션 단위로 명확
개별 메시지 라우팅·우선순위·지연 전송강하다약하다 — 브로커가 단순한 대신 처리량을 얻는다
  • 직접 연동의 통증은 전부 결합 — 시간(둘 다 살아 있어야) · 속도(폭주 전염) · 코드(N×M)
  • Kafka를 놓는 목적은 결합을 시간 축에서 끊는 것 — 생산자는 쓰고 끝, 소비자는 제 속도로
  • 큐와의 본질 차이는 읽어도 남는다는 것 — 다중 구독·재처리가 여기서 나온다
  • 대가는 비동기와 중복 가능성 — “두 번 받아도 무해하게”가 소비자의 기본 자세다(6장)