Kafka 이벤트 흐름 설계
Producer·Topic·Consumer·Partition·Key 설계로 확장성과 재처리 한계를 결정하는 Kafka 아키텍처 가이드
요약 (5–7줄)
Kafka는 큐가 아니라 로그 기반 상태 전파 장치다.
Producer/Topic/Consumer 설계는 단순 구현 문제가 아니라 확장·장애·재처리의 한계를 결정하는 아키텍처 결정이다.
토픽은 책임 경계, 파티션은 병렬성, 키는 순서와 장애 범위를 정의한다.
Kafka는 기본적으로 at-least-once 전달을 전제로 하며, 이를 무시한 설계는 운영 단계에서 반드시 깨진다.
이벤트 계약(스키마)은 코드보다 강한 결합 지점이다.
이 편의 목적은 Kafka를 “메시지 전달”이 아니라 “시간축을 가진 데이터 시스템”으로 인식하게 만드는 것이다.
1. 정의
Kafka 이벤트 흐름은 Producer가 이벤트를 로그(Topic)에 append하고, Consumer가 오프셋을 기준으로 이를 소비하는 구조다.
핵심은 “전달”이 아니라 순서가 보존된 기록이다.
2. 직관
큐는 “꺼내면 사라진다”.
Kafka 로그는 “기록되고, 다시 읽을 수 있다”.
이 차이 하나가 재처리·확장·장애 복구 전략을 완전히 갈라놓는다.
3. 확장 단위 관점에서의 핵심 구성 요소
3.1 Topic
- 의미: 도메인 이벤트 스트림
- 확장 관점: 책임 분리 단위
- 잘못된 예: 여러 도메인 이벤트를 하나의 토픽에 혼합
3.2 Partition
- 의미: 순서가 보장되는 최소 단위
- 확장 관점: 병렬 처리의 상한선
- 파티션 수 = 최대 동시 처리량
3.3 Key
- 의미: 순서·장애·확장 범위를 묶는 기준
- 확장 관점: “어디까지 함께 묶을 것인가”에 대한 결정
3.4 Consumer Group
- 의미: 확장 가능한 소비자 집합
- 확장 관점: 동일 로직의 수평 확장 단위
4. Producer 설계의 핵심 5가지
4.1 이벤트 스키마
- 이벤트는 로그에 남는다 → 과거까지 책임
- 필드 제거/의미 변경은 즉시 장애로 이어짐
4.2 키 전략
- 키 = 순서 보장 범위
- 너무 넓으면 병목, 너무 좁으면 순서 붕괴
4.3 멱등성
- 재시도는 기본 전제
- Producer 멱등 + Consumer 멱등은 별개 문제
4.4 재시도 / 백오프
- 즉시 재시도는 장애 증폭기
- 지수 백오프 + 제한 횟수 필수
4.5 순서 보장 범위
- 파티션 내부만 보장
- “전체 순서”를 기대하는 순간 설계 실패
5. Consumer 설계의 핵심 5가지
5.1 오프셋 커밋 전략
- 자동 커밋: 단순하지만 위험
- 수동 커밋: 처리 완료 기준을 명확히 정의
5.2 중복 처리
- at-least-once의 필연적 결과
- 상태 기반 멱등성 필요
5.3 재처리 (Replay)
- 오프셋을 되돌릴 수 있어야 함
- 비결정적 로직이 있으면 재처리 불가
5.4 DLQ / Poison Pill
- 처리 불가능한 이벤트를 격리
- 무한 재시도 금지
5.5 처리량 튜닝
- poll 크기, 처리 시간, 커밋 주기 간 균형
- 느린 Consumer 하나가 전체 그룹을 지연시킴
6. 왜 at-least-once를 기본으로 두고 설계해야 하는가
사례
결제 완료 이벤트 소비 중 네트워크 단절 발생
- 오프셋 커밋 전 장애 → 이벤트 재전달
- exactly-once를 가정했다면 중복 결제 처리 발생
Kafka는 중복을 허용하고, 소비자가 책임지는 모델이다.
이를 부정하는 설계는 운영 단계에서 반드시 데이터 오염으로 귀결된다.
7. 이벤트 계약과 스키마 호환성
7.1 이벤트 계약의 의미
- API보다 변경 비용이 큼
- 한 번 발행된 이벤트는 “역사”
7.2 호환성 개념
- Backward: 새 소비자가 과거 이벤트 처리 가능
- Forward: 기존 소비자가 새 이벤트 처리 가능
- Full: 양방향 호환
운영 환경에서는 Backward 호환을 기본 전제로 둔다.
8. 최소 예시
8.1 Toy 예시: 주문 생성 이벤트
- Topic:
order-created - Key:
orderId - Partition: 주문 단위 순서 보장
- Consumer Group:
- 결제 처리
- 알림 발송
→ 주문별 순서는 보장, 주문 간 병렬 처리 가능
8.2 실무 예시: 검색 인덱싱 파이프라인
- 문서 변경 이벤트 수집
- 중복: 동일 문서 ID 기준 멱등 처리
- 순서: 최신 버전 타임스탬프 비교
- 재처리: 전체 오프셋 리셋 후 재인덱싱 가능
9. 트레이드오프
- 장점: 재처리 가능성, 확장성, 장애 복원력
- 비용: 설계 복잡도, 운영 규율 필요, 지연 허용
Kafka는 편의성보다 통제력을 제공하는 시스템이다.
10. 실무 함정 → 해결 패턴
| 함정 | 결과 | 해결 패턴 |
|---|---|---|
| 키 미설계 | 순서 붕괴 | 도메인 기준 키 |
| 파티션 과소 | 확장 불가 | 초기 여유 파티션 |
| 자동 커밋 | 데이터 유실 | 명시적 커밋 |
11. 오해/실수 3개 + 교정
1) “Kafka는 큐다” → 로그다
2) “Exactly-once면 안전” → 현실적으로 비용 과다
3) “키는 아무 문자열이나” → 아키텍처 결정
12. 판단 기준
사용해야 할 때
- 이벤트 재처리가 요구됨
- 소비자가 여러 개로 확장됨
- 장애 격리가 중요함
쓰지 말아야 할 때
- 단순 1:1 비동기 통신
- 운영 인력 부족
- 순차 처리만 필요한 소규모 시스템
13. 재학습 체크리스트 (10–14)
- 토픽이 도메인 단위로 분리됐는가?
- 파티션 수는 미래 확장을 고려했는가?
- 키는 비즈니스 규칙을 반영하는가?
- Producer 재시도는 제한돼 있는가?
- Consumer는 멱등한가?
- 오프셋 커밋 기준은 명확한가?
- DLQ가 존재하는가?
- 재처리가 가능한 구조인가?
- 스키마 변경 전략이 있는가?
- Backward 호환을 지키는가?
- 처리 지연 허용 범위는?
- 장애 시 복구 절차가 있는가?
반드시 포함할 항목
키를 잘못 잡았을 때 생기는 장애 3종
1) 핫 파티션으로 인한 처리 지연
2) 순서 붕괴로 인한 상태 오염
3) 장애 범위 과도 확장리플레이 가능한 시스템의 전제조건 4개
1) 결정적 로직
2) 멱등성
3) 충분한 로그 보존
4) 외부 사이드이펙트 통제
