티스토리 뷰
아래 글은 Kafka Consumer가 애플리케이션에서 담당하는 역할부터 컨슈머 그룹으로 확장되는 병렬 처리 모델, 그리고 오프셋 관리 전략(자동·수동 커밋)을 체계적으로 설명한 전문가용 가이드입니다. Java SDK와 kafka-python을 이용해 바로 실행 가능한 최소-예제 코드를 제공하며, 각 설정이 실전에 미치는 영향과 주의점을 최신 문서와 커뮤니티 사례를 근거로 정리했습니다. 이 글 한 편이면 “왜 이렇게 설계됐고, 어떻게 쓰면 안전·고성능인가?” 를 모두 이해하실 수 있습니다.
1 | 컨슈머의 핵심 역할
Kafka Consumer는 브로커에 저장된 파티션 로그를 읽어 비즈니스 로직으로 전달하는 계산 계층입니다. poll() 루프 안에서 레코드를 가져오고, 오프셋 위치 를 중심으로 재시작·장애 복구·재처리를 제어합니다. “스토리지는 브로커, 컴퓨트는 컨슈머” 라는 Kafka 분리 원칙의 출발점이 바로 이 컴포넌트입니다.
2 | 컨슈머 그룹: 왜 중요한가?
2-1. 스케일-아웃과 고가용성
동일 group.id 의 컨슈머를 여러 대 띄우면 파티션이 자동 분배(Assign)되어 병렬 처리량이 선형 확장됩니다. 새 컨슈머가 합류·이탈할 때 리밸런스 프로토콜이 동작해 부담을 고르게 재조정합니다.
2-2. Exactly-Once 의 단서
컨슈머 그룹은 “파티션당 단일 컨슈머” 원칙 덕분에 메시지 순서를 유지합니다. 따라서 멱등 프로듀서와 결합하면 파티션 단위에서 정확-한-번 처리가 가능합니다.
3 | 오프셋 관리 전략
전략 특징 설정 키
| 자동 커밋 | 주기(auto.commit.interval.ms)마다 브로커의 __consumer_offsets 토픽에 오프셋 저장 → 구현 단순, at-least-once | enable.auto.commit=true (기본) |
| 수동(동기) 커밋 | 처리 완료 후 commitSync() 호출 → 실패 시 재시도, 데이터 유실 최소화 | enable.auto.commit=false |
| 수동(비동기) 커밋 | commitAsync() → 지연·TPS 향상, 실패 재시도는 직접 처리 | 동일 |
힌트 – auto.offset.reset
초기 오프셋이 없을 때 소비 시작 위치를 결정합니다. earliest = 0부터, latest = 끝에서. 실시간 서비스는 latest, 배치 리플레이는 earliest를 주로 사용합니다.
내부적으로 커밋된 오프셋은 __consumer_offsets 토픽에 칸별 키-값으로 저장되며, 브로커 장애 시에도 동일 클러스터 안에서 안전하게 복구됩니다.
4 | Java 컨슈머 최소 예제
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ConsumerConfig.GROUP_ID_CONFIG, "blog-demo");
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); // 수동 커밋
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
"org.apache.kafka.common.serialization.StringDeserializer");
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); // 처음이면 0부터
try (KafkaConsumer<String,String> c = new KafkaConsumer<>(props)) {
c.subscribe(List.of("quickstart"));
while (true) {
ConsumerRecords<String,String> recs = c.poll(Duration.ofMillis(500));
for (ConsumerRecord<String,String> r : recs) {
// TODO: 비즈니스 처리
}
c.commitSync(); // 동기 커밋으로 정확성 확보
}
}
commitSync() 는 네트워크 오류가 나면 재시도하며, 리밸런스 직전에도 자동 호출하여 중복 소비를 줄여 줍니다.
5 | Python (kafka-python) 컨슈머 예제
from kafka import KafkaConsumer
import json, logging
consumer = KafkaConsumer(
'quickstart',
bootstrap_servers='localhost:9092',
group_id='blog-demo',
enable_auto_commit=False,
auto_offset_reset='earliest',
key_deserializer=lambda k: k.decode() if k else None,
value_deserializer=lambda v: json.loads(v.decode())
)
for msg in consumer:
process(msg.value) # 비즈니스 로직
consumer.commit() # 기본은 동기; 별도 쓰레드에서 비동기 커밋도 가능
kafka-python 은 commit_async() 도 지원하니 고TPS 환경에서 고려하세요.
6 | 모범 사례 & 트러블슈팅
- 리밸런스 최적화 – 메시지 처리 시간이 길다면 max.poll.interval.ms 를 충분히 늘리고, cooperative-sticky 파티셔너로 재조정 비용을 줄입니다.
- 오프셋-업데이트 패턴 – 데이터베이스 트랜잭션과 함께 커밋하려면 Outbox 패턴 또는 브로커 트랜잭션 API를 활용해 exactly-once 를 완성합니다.
- dead-letter 대응 – 역직렬화 예외 등 비즈니스 에러는 재처리 내역 을 별도 토픽으로 보내고, 원본 토픽 오프셋은 정상 커밋해 파이프라인 정체를 막습니다.
7 | 맺음말
컨슈머는 Kafka 파이프라인에서 “읽기·계산·커밋” 3단계를 구현하며, 컨슈머 그룹을 통해 무중단 스케일-아웃·장애 복구 능력을 갖춥니다. 자동 커밋은 학습·프로토타이핑에 빠르고, 실전 서비스는 수동 커밋 + 예외 관리 로 정확성을 확보하는 것이 정석입니다. 본문의 Java·Python 예제를 토대로 자신만의 컨슈머 모듈을 템플릿화해 두면, 어떤 스트리밍 프로젝트에서도 안정적인 데이터 소비를 시작할 수 있습니다.
'개발 인프라 > 카프카' 카테고리의 다른 글
| 주키퍼(ZooKeeper)는 이제 안녕? KRaft 모드 알아보기 (0) | 2025.05.22 |
|---|---|
| 카프카 토픽과 파티션, 왜 중요할까? (1) | 2025.05.21 |
| 카프카 프로듀서(Producer) 란? (2) | 2025.05.16 |
| 로컬 카프카 설치부터 메시지 전송/수신 (1) | 2025.05.16 |
| 카프카(Kafka)란 무엇인가? (0) | 2025.05.14 |
- Total
- Today
- Yesterday
- springai
- 타입 안전성
- Java
- 스브링부트
- 일급 객체
- MCP
- 언리얼엔진5
- method Area
- 디자인패턴
- ai통합
- generated_body()
- AI 에이전트
- unreal engjin
- Claude Agent SDK
- redis
- Subagent
- First-class citizen
- JAVA 프로그래밍
- 코틀린
- Stack Area
- 언리얼엔진
- 자바
- cqrs
- Heap Area
- 코프링
- vite
- 카프카 개념
- RESTfull
- model context protocol
- JVM
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
