Kafka Producer는 단순히 메시지를 전송하는 컴포넌트가 아니다.
내부적으로는 대규모 고속 전송을 위한 버퍼링·배치·압축·재전송·멱등성·순서 관리까지 수행하는 매우 정교한 구조이다.
Producer를 제대로 이해하면 다음 문제들을 스스로 분석할 수 있다.
- 왜 특정 상황에서 메시지가 중복 전송되는가
- 어떤 설정이 처리량을 극적으로 높이는가
- acks=all이 왜 중요하며 언제 실패하는가
- 재전송이 무한 루프로 빠지는 이유
- 멱등성(idempotence)이 없을 때 어떤 장애가 발생하는가
- 파티션별 순서가 언제 보장되는가
이번 편에서는 Kafka Producer의 핵심 구조를 깊게 설명한다.
1. Producer 내부 구조: RecordAccumulator
Producer는 메시지를 전송할 때 바로 네트워크로 보내지 않는다.
먼저 RecordAccumulator라는 메모리 버퍼에 저장한다.
RecordAccumulator 동작 방식
- Producer가 send() 호출
- 메시지가 Partition별로 Accumulator에 저장
- Accumulator는 메시지를 batch 단위로 묶음
- Sender thread가 별도로 batch를 Broker에 전송
왜 이런 구조인가?
- 메시지 1건씩 전송하면 네트워크 비용이 매우 큼
- Accumulator는 여러 이벤트를 묶어서 “한 번에” 전송함 → 처리량 증가
- Partition별로 독립된 큐를 가져 병렬 처리 가능

그림으로 다시보자.
- Producer는 ProducerRecord를 생성하고 Serializer가 이를 byte 배열로 변환한다.
- Partitioner가 메시지가 들어갈 Topic-Partition을 결정한다.
- RecordAccumulator는 Partition별로 Batch를 생성해 메시지를 메모리 버퍼에 쌓는다.
- Sender 스레드가 준비된 Batch를 모아 Kafka 클러스터의 해당 Partition Leader로 전송한다.
- 이 구조 덕분에 Producer는 네트워크 I/O에 묶이지 않고 높은 처리량을 얻는다.
2. Batch + Compression: Producer 성능의 핵심
Producer는 메시지를 batch로 묶어서 단 한 번의 네트워크 호출로 전송한다.
배치(Batch)의 이점
- 네트워크 요청 수 감소 → TPS 증가
- 압축 효율 증가
- Broker에 전달되는 레코드 덩어리가 커서 스루풋 향상
Producer는 아래 두 설정에 영향을 받는다.
batch.size
- 배치 하나의 최대 크기 (기본 16KB~32KB)
- batch가 이 크기까지 차면 즉시 전송
linger.ms
- 배치를 기다리는 시간
- 메시지가 적게 들어오면 linger.ms가 찰 때까지 기다렸다가 전송
- high throughput → batch.size↑ + linger.ms↑
- low latency → linger.ms=0
압축(Compression)
Producer는 메시지를 Broker에 보내기 전에 압축할 수 있다.
- gzip
- snappy
- lz4
- zstd (추천, 최신/고효율)
압축은 Producer와 Broker 사이에서만 발생하고, Follower Replica는 이미 압축된 그대로 받아 복제한다.

그림으로 다시보자.
- Producer는 메시지를 직렬화·파티셔닝한 뒤 Accumulator의 Topic별 버퍼에 저장한다.
- Accumulator는 메시지를 batch.size 기준으로 Batch 1, Batch 2처럼 묶어서 관리한다.
- linger.ms 동안 메시지를 모았다가 Batch가 준비되면 Sender가 Broker로 전송한다.
- 이 구조로 Producer는 네트워크 호출을 최소화하고 높은 처리량을 확보한다.
3. ACKS=0 / 1 / ALL 차이
Producer가 send() 후 언제 “성공”으로 간주할지는 acks 설정으로 결정한다.
acks=0
- Producer는 전송 후 응답을 기다리지 않음
- 속도 가장 빠름
- 유실 위험 매우 큼
- 모니터링 로그/metric 등 유실 허용 가능한 환경에서만 사용
acks=1
- Leader가 메시지를 파일에 append한 것만 확인
- ISR 복제는 확인하지 않음
- Leader 장애 시 데이터 유실 가능
acks=all (= -1)
- Leader + 모든 ISR Replica에 복제 완료된 후 성공 반환
- 가장 안전한 설정
- 금융/주문/결제 시스템에서는 필수
요약하면..
- 성능 1순위 → acks=0
- 성능/안정성 적당히 → acks=1
- 안전성 절대우선 → acks=all
4. Retries와 재전송
Kafka Producer는 메시지 전송 실패 시 자동으로 재시도한다.
하지만 재시도에는 치명적인 문제가 숨어 있다.
Retries 기본 개념
다음 상황에서 Retry가 발생한다.
- 네트워크 타임아웃
- Leader not available
- Follower lag 초과로 ISR 축소
- UnknownTopicOrPartition
- Request too large
Retry 문제가 왜 위험한가?
retry는 동일 메시지를 다시 보내므로 중복 메시지 발생 가능
특히 acks=1 + retry 조합은 대표적인 중복 전송 패턴이다.
예시
- Producer가 메시지를 Leader에 전송
- Leader는 기록했지만 Producer에게 응답을 보내는 중 네트워크 단절
- Producer는 “실패”로 판단하고 다시 send()
- 같은 메시지가 두 번 저장됨
이런 중복을 막기 위한 기능이 Idempotent Producer 이다.
5. Idempotent Producer (중복 없는 전송)
Kafka 0.11부터 idempotent producer 기능을 제공한다.
Producer가 중복 전송하더라도 Broker가 동일 메시지를 중복 저장하지 않는다.
활성화 방법
enable.idempotence=true
Idempotent Producer 동작 원리
- Producer는 PID(Producer ID)와 sequence number를 부여
- Broker는 Partition별로 "마지막 sequence number"를 기억
- 같은 PID + 같은 sequence number 메시지는 중복으로 판단하고 무시
즉, retry가 몇 번 일어나도 논리적으로 한 번만 전송된 것처럼 처리된다.
장점
- 메시지 중복 방지
- retry가 많은 환경에서도 데이터 무결성 유지
단점
- 하나의 Producer가 여러 Transactional 작업을 동시에 하기에는 제한적
- Partition 단위 멱등성만 제공됨

그림으로 다시보자.
- Producer는 메시지를 전송하고 Broker는 정상적으로 커밋한 후 ACK을 보낸다.
- 하지만 네트워크 장애로 ACK이 Producer에게 도착하지 않으면 Producer는 실패로 판단한다.
- Producer는 같은 메시지를 retry 전송하지만 Idempotent Producer는 PID+Sequence 번호를 확인한다.
- Broker는 이미 처리한 메시지임을 인지하고 중복을 무시한다.
- 결과적으로 재전송이 발생해도 메시지는 단 한 번만 커밋된다.
6. Message Ordering 보존 조건(순서 보장 조건)
Kafka는 “Partition 단위”로만 순서를 보장한다.
하지만 Producer가 몇 가지 조건을 위반하면 순서가 깨질 수 있다.
Producer 순서가 깨지는 조건
-
같은 Partition에 대해 동시에 여러 배치(batch)가 전송될 때
Batch 1: [msg 1, msg 2, msg 3]
Batch 2: [msg 4, msg 5]
위 상황처럼 하나의 Partition에 여러 배치가 있다고하자.
그랬을때 네트워크 경로가 다르거나, retry가 발생하거나, 배치1이 압축되어 더 오래걸리거나 .. 여러 상황이 있을수있겠지만 배치2가 먼저 도착해버린다면 ?
그럼 순서가 뒤집히게된다. (msg 4 → msg1)
-
retries > 0 + acks=0 조합
-
max.in.flight.requests.per.connection > 1 (기본은 5)
이 설정은 “동시에 몇 개의 요청을 브로커로 날릴 수 있는가”다.
즉 5라면 Producer는 한 커넥션에서 동시에 5개의 배치를 전송할수있다.
근데 여기서 문제는 ?
배치1이 전송됨, 배치 2도 전송, 배치1이 retry 발생.. 늦게 도착
그 사이에 배치2가 commit 돼버림. 이렇게 되면 순서가 뒤바뀐다.
-
Producer가 여러 스레드에서 같은 Producer instance를 공유할 때
순서 보장을 원한다면?
아래 설정이 필수
enable.idempotence=true
max.in.flight.requests.per.connection=1
acks=all
이 조합이면, retry가 발생해도 메시지 순서가 보장된다.
7. Backpressure와 Producer 처리량 최적화
Kafka Producer는 메시지를 계속 빠르게 보내고싶어한다.
그래서 Producer는 Broker가 처리 속도가 느릴 때 자동으로 backpressure를 만든다.
대표적인 backpressure 조건
- RecordAccumulator이 꽉 참 (buffer.memory 초과)
- batch가 너무 많이 밀림
- Broker 응답 지연
- 네트워크 지연 증가
이 과정에서 Producer는 다음 동작을 한다.
- 새로운 send() 요청 block
- enqueue 안 됨
- timeout 발생
- retries 증가
Producer 성능 튜닝 핵심
-
batch.size ↑
더 적은 네트워크 호출 = 높은 처리량
-
linger.ms ↑
배치를 얼마나 모을 것인가 ?
linger.ms를 키우면 배치가 충분히 커진 뒤 전송 = 성능 상승
-
compression.type=zstd
-
buffer.memory ↑
-
max.in.flight.requests.per.connection 조정
값이 크면 → 높은 처리량, 값이 작으면 → 순서 보존
-
acks=all + idempotence 안정화
올바른 설정 조합만 맞춰줘도 Producer 처리량은 2배~10배까지 상승할 수 있다.
8. 정리
Kafka Producer는 단순 HTTP client와 비교할 수 없을 만큼 복잡하고 정교하다.
핵심 개념을 요약하면 다음과 같다.
- RecordAccumulator는 Producer 성능의 핵심 버퍼
- batch + linger.ms 조합은 Throughput에 절대적
- acks=all은 내구성과 안정성을 위한 기본값
- retry는 중복을 일으키므로 idempotence 필수
- ordering 보장은 설정 조합이 맞아야 유지됨
- backpressure는 Producer-Broker 부하 균형을 맞추는 핵심 메커니즘
Producer 구조를 확실히 이해하면 Kafka 메시지 전송 중 발생하는 대부분의 문제(중복, 지연, 순서깨짐, ACK 실패)를 스스로 분석하고 해결할 수 있다.
참고문헌
https://zzzzseong.tistory.com/106
https://magpienote.tistory.com/251
https://www.geeksforgeeks.org/apache-kafka/apache-kafka-idempotent-producer/