카프카 마스터 노트 시리즈 1편. 이벤트 드리븐 아키텍처(EDA)가 모놀리식 동기 통신의 한계를 푸는 방식, Kafka가 LinkedIn에서 탄생한 배경, 메시지 브로커 vs 스트리밍 플랫폼의 차이, KRaft 모드가 Zookeeper를 대체한 이유, Kafka의 4대 핵심 API(Producer·Consumer·Streams·Connect)까지 — 시리즈의 토대를.
이 글은 카프카 마스터 노트 시리즈의 첫 번째 편입니다. 마이크로서비스가 늘어나면 동기 REST 호출만으로는 묶이지 않습니다. 그때 등장하는 게 이벤트 드리븐 아키텍처(EDA), 그리고 그 표준 도구가 Kafka.
이 시리즈 15편은 Kafka 기초·Topic/Partition·Producer/Consumer·Consumer Group·Reactor Kafka·Cluster·배치/에러/트랜잭션·Spring Kafka까지 다룹니다. 1편의 목표 — EDA를 왜 쓰는지, Kafka가 무엇인지 손에 잡히게.
이 시리즈는 Apache Kafka 공식 문서, Confluent 학습 자료, 여러 Kafka 학습 노트 등 공개 자료를 참고해 한국어 학습 노트로 풀어쓴 자료입니다.
로컬에 Docker로 Kafka 한 노드를 띄우고 토픽에 메시지를 직접 넣고 빼 보면 흐름이 한 번에 잡혀요. 30분이면 첫 Producer/Consumer 흐름이 손에 들어옵니다.
처음 EDA·Kafka가 어렵게 느껴지는 이유
처음 이 단원이 어렵게 느껴지는 이유는 두 가지예요. 첫째, "이벤트 드리븐"이라는 단어가 모호합니다. 그냥 메시지큐 아닌가? 카프카는 그것과 뭐가 다른가? 둘째, 카프카 용어가 한 번에 쏟아져서. 토픽·파티션·브로커·컨슈머그룹·KRaft… 누가 누구 위에 올라가는지 안 보입니다.
해결법은 한 가지예요. "신문 발행소" 비유로 묶는 것. Kafka = 신문사 발행소, Topic = 신문 종류, Partition = 같은 신문의 여러 인쇄기, Broker = 발행소 건물, Producer = 기자, Consumer = 구독자. 이 그림이 잡히면 모든 동작이 따라옵니다.
EDA — 왜 등장했나
모놀리식·동기 호출의 한계
Order Service ─REST→ Payment Service ─REST→ Inventory ─REST→ Shipping
↓
모두 응답 후 완료
문제:
- 강결합 — 한 서비스 다운 시 전체 멈춤
- 느림 — 모든 응답 대기
- 확장 어려움 — 트래픽 폭주 시 N개 모두 키워야
EDA — 비동기 + 느슨한 결합
Order Service → [OrderCreated 이벤트] → Kafka
↓
Payment / Inventory / Shipping이 각자 구독
장점:
- 느슨한 결합 — 다른 서비스가 무엇을 하는지 몰라도 됨
- 비동기 — 즉시 응답, 처리는 백그라운드
- 확장 독립 — 부하 큰 서비스만 키움
- 이력 보존 — 모든 이벤트가 영속화
여기서 정말 중요한 시험 함정 — EDA = "사실(이벤트)을 발행하고, 관심 있는 자가 반응". 명령(command) 모델과 다름. Order Service는 "주문이 생겼다"만 알리고, 누가 어떻게 처리할지 신경 X.
Kafka — 단순 메시지큐가 아니다
메시지큐 vs 스트리밍 플랫폼
| 구분 | 전통 메시지큐 (RabbitMQ·ActiveMQ) | Kafka |
|---|---|---|
| 메시지 보존 | 소비 후 삭제 | 로그처럼 영속 (보존 기간) |
| 다중 구독 | 어려움 | 자연스러움 (여러 그룹 독립) |
| 처리량 | 수만 메시지/초 | 수백만/초 (수평 확장) |
| 재처리 | 어려움 | 오프셋 되감기로 쉬움 |
| 모델 | Push (브로커 → 컨슈머) | Pull (컨슈머가 가져감) |
여기서 정말 중요한 시험 함정 — Kafka는 분산 로그(Distributed Log). 메시지가 사라지지 않고 디스크에 영속. 새 컨슈머가 와서 처음부터 다시 읽어도 OK. 이게 메시지큐와 결정적 차이.
Kafka의 탄생 — LinkedIn 2010
LinkedIn에서 사용자 행동 로그(클릭·페이지뷰)를 수집할 때, 기존 메시지큐론 처리 못함:
- 초당 수십만 이벤트
- 수십 다양한 컨슈머
- 며칠치 데이터 다시 읽고 싶음
커밋 로그(Commit Log) 개념을 분산 환경에 적용 → Kafka 탄생. 2011년 오픈소스화, Apache 재단으로.
Kafka 4 핵심 API
1. Producer API — 이벤트 발행
2. Consumer API — 이벤트 구독·소비
3. Streams API — 실시간 스트림 처리 (필터·집계·조인)
4. Connect API — 외부 시스템 연동 (DB → Kafka, Kafka → S3 등)
대부분 입문 단계에선 Producer·Consumer만. Streams·Connect는 고급.
핵심 컴포넌트 — 신문사 비유로
1. Topic — 신문 종류
order-events (주문 신문)
payment-events (결제 신문)
shipping-events (배송 신문)
이벤트의 분류 단위. DB 테이블과 비슷한 개념.
2. Partition — 같은 신문의 여러 인쇄기
order-events 토픽:
├── partition 0 (인쇄기 1)
├── partition 1 (인쇄기 2)
└── partition 2 (인쇄기 3)
병렬 처리·수평 확장의 핵심. 자세한 건 2편에서.
3. Broker — 발행소 건물
Kafka 서버 1대 = Broker 1대. 클러스터 = 여러 브로커.
4. Producer — 기자
이벤트를 토픽에 발행.
5. Consumer — 구독자
이벤트를 토픽에서 소비.
6. Consumer Group — 구독자 단체
여러 컨슈머 인스턴스가 한 그룹. 같은 토픽을 그룹 단위로 분담. 4편에서 자세히.
KRaft — Zookeeper의 종말
Zookeeper 시대 (~2.8)
Kafka 클러스터 관리(브로커 목록·리더 선출·메타데이터)를 Zookeeper에 위임:
[Kafka 브로커들]
↕ (메타데이터)
[Zookeeper 클러스터]
문제:
- 시스템 2개 운영 (Kafka + Zookeeper)
- 메타데이터 동기화 비용
- 일관성 문제 — 두 시스템 사이
KRaft 모드 (Kafka 2.8+ 도입, Kafka 3.3+ 정식)
Kafka 자체가 메타데이터 관리 (Raft 합의 알고리즘 기반).
[Kafka 브로커] (그 중 일부 = Controller)
↕ (자체 합의)
장점:
- 시스템 1개
- 일관성 강화
- 메타데이터 처리 매우 빠름
- 백만+ 파티션 지원
여기서 정말 중요한 시험 함정 — KRaft가 신규 표준. Kafka 3.3+ 공식 권장. 새 프로젝트는 KRaft. 기존 Zookeeper 운영 중이면 마이그레이션 가이드 따라 전환.
Controller 노드
KRaft에서 클러스터 관리 담당하는 특수 브로커. 정족수(quorum) 합의로 결정.
메시지·이벤트 vs 레코드
메시지 (Message) ─┐
이벤트 (Event) ─┼─ 같은 의미 (문맥에 따라 다른 명칭)
레코드 (Record) ─┘
Kafka API에선 주로 Record. 비즈니스 관점에선 Event. 일반 통신 관점에선 Message. 모두 "토픽에 쓰여지는 데이터 한 단위" 의미.
메시지 구조
Record:
- Key (선택, 파티셔닝 결정)
- Value (필수, 실제 데이터)
- Headers (선택, 메타데이터)
- Timestamp
- Topic·Partition·Offset
여기서 시험 함정이 하나 있어요. Key는 선택이지만 거의 항상 사용. 같은 Key는 같은 파티션 → 순서 보장. user_id, order_id 같은 비즈니스 ID로 쓰는 게 표준.
이벤트 드리븐 마이크로서비스 — 큰 그림
주문 흐름:
[Order Service]
↓ OrderCreated → order-events 토픽
├── [Payment Service] 구독 → 결제 처리 → PaymentDeducted → payment-events
├── [Inventory Service] 구독 → 재고 차감 → InventoryDeducted → inventory-events
└── [Notification Service] 구독 → 알림 발송 (응답 토픽 X)
이때:
- Order Service는 다른 3 서비스가 뭘 하는지 모름
- 각 서비스는 독립 확장 가능
- 한 서비스 다운돼도 이벤트는 보관됨 (복구 후 처리)
Pull vs Push 모델
RabbitMQ: 브로커 → 컨슈머에게 Push
- 컨슈머 부담 ↑ (느린 컨슈머 죽음)
Kafka: 컨슈머 → 브로커에서 Pull
- 컨슈머 페이스 조절 가능
- 백프레셔 자연스러움
Pull 모델 = Kafka 안정성의 핵심.
시험 직전 한 번 더 — 자주 헷갈리는 함정 모음
여기까지가 1편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.
- EDA = 비동기 + 느슨한 결합 + 이력 보존
- 이벤트 = "사실 발행 + 관심 있는 자가 반응"
- 명령(command) 모델과 다름
- Kafka ≠ 단순 메시지큐
- 메시지 보존 (로그처럼) — 소비 후 안 사라짐
- 다중 구독 자연스러움 (여러 그룹 독립)
- 처리량 수백만/초
- 오프셋 되감기로 재처리 쉬움
- Pull 모델 (컨슈머가 가져감)
- LinkedIn 2010 탄생, 커밋 로그를 분산 환경에
- 4 API — Producer / Consumer / Streams / Connect
- 6 컴포넌트 — Topic / Partition / Broker / Producer / Consumer / Consumer Group
- Topic = 이벤트 분류 (신문 종류)
- Partition = 토픽 분할 (병렬 처리)
- Broker = Kafka 서버 1대
- KRaft = Zookeeper 대체, Kafka 3.3+ 정식
- KRaft = 시스템 1개·일관성 강화·백만+ 파티션
- Controller = KRaft에서 클러스터 관리 담당
- 새 프로젝트는 KRaft 권장
- 메시지/이벤트/레코드 = 같은 의미
- Record 구조 — Key·Value·Headers·Timestamp·Topic/Partition/Offset
- Key는 선택이지만 거의 항상 사용 (같은 Key = 같은 파티션 = 순서 보장)
- user_id·order_id 같은 비즈니스 ID로
- Pull vs Push — Kafka는 Pull, RabbitMQ는 Push
시리즈 다른 편
- 1편 — EDA·Kafka 기초·KRaft (현재 글)
- 2편 — Topic·Partition·Offset
- 3편 — Producer·Consumer 동작
- 4편 — Consumer Group·리밸런싱
- 5편 — Reactor Kafka
- 6편 — Cluster·HA·Best Practices
- 7편 — 배치·에러·트랜잭션
- 8편 — Spring Kafka·테스트·보안
- 9편 — Spring Cloud Stream 기초
- 10편 — StreamBridge 동적 라우팅
- 11편 — Fan-Out / Fan-In
- 12편 — SCS Tips & Tricks
- 13편 — Saga 코레오그래피
- 14편 — Saga 오케스트레이터
- 15편 — Transactional Outbox
공식 문서: Apache Kafka Documentation / KRaft Mode 에서 더 깊이.
다음 글(2편)에서는 Topic·Partition·Offset·Segment — Kafka 데이터 구조의 4계층을 풀어 갑니다.