본문 바로가기
카테고리 없음

Kafka 프로듀서 전송원리

by sujupark54 2026. 2. 6.

코딩하는 이미지

Kafka에서 프로듀서는 메시지를 생성해 브로커로 전달하는 시작점 역할을 한다. Kafka를 처음 접하면 단순히 send() 메서드로 메시지를 보내는 수준에서 이해하기 쉽지만, 실제로 내부에서는 여러 단계의 처리 과정을 거쳐 안정성과 처리량을 동시에 확보한다. 이 글에서는 Kafka 프로듀서의 기본 구조와 메시지가 브로커로 전달되기까지의 전송 원리를 흐름 중심으로 정리하고, 전송 결과 확인 방식과 전송 보장 설정까지 함께 살펴본다.


Kafka 프로듀서 내부구조

Kafka 프로듀서의 내부 구조는 성능과 안정성을 동시에 확보하기 위해 단계적으로 구성되어 있다. 프로듀서가 메시지를 전송하면 가장 먼저 Serializer가 동작한다. Serializer는 애플리케이션에서 전달한 메시지를 Kafka가 이해할 수 있는 byte 배열 형태로 변환한다. 이 과정에서 문자열, JSON, Avro 등 다양한 직렬화 방식이 사용될 수 있으며, 직렬화 방식에 따라 네트워크 사용량과 처리 비용이 달라진다.

직렬화가 완료된 메시지는 Partitioner로 전달된다. Partitioner는 해당 메시지를 어떤 토픽의 어떤 파티션으로 보낼지 결정한다. 메시지 키가 존재할 경우 동일한 키는 동일한 파티션으로 전달되어 순서를 보장하고, 키가 없을 경우에는 라운드 로빈 방식 등으로 파티션이 선택된다. 이 단계에서 메시지 분산 전략이 결정되며, 전체 처리량과 병렬성에 큰 영향을 미친다.

파티션이 결정된 메시지는 곧바로 네트워크로 전송되지 않는다. 메시지는 프로듀서 내부 버퍼에 쌓이고, 일정 크기나 시간 조건이 충족되면 배치 단위로 묶인다. 이 배치 구조 덕분에 네트워크 요청 횟수가 줄어들고 처리량이 크게 향상된다. Sender 스레드는 별도로 동작하며, 배치가 준비되는 대로 Kafka 브로커로 메시지를 전송한다. Send와 Sender가 분리되어 있기 때문에 프로듀서는 메시지를 보내는 동안에도 계속해서 새로운 메시지를 수집할 수 있다.


Kafka 프로듀서 전송결과

Kafka 프로듀서는 메시지를 전송한 뒤 결과를 확인할 수도 있고, 결과를 기다리지 않고 바로 다음 작업을 수행할 수도 있다. 가장 단순한 방식은 전송 결과를 확인하지 않는 것이다. producer.send() 메서드를 호출하고 반환값을 무시하면, 메시지가 성공했는지 실패했는지 알 수 없다. 이 방식은 로그 수집이나 통계 이벤트처럼 실패해도 큰 문제가 없는 메시지에 적합하다.

전송 결과를 확인하는 첫 번째 방법은 Future를 사용하는 방식이다. send() 메서드는 내부적으로 Future를 반환한다. Future.get()을 호출하면 메시지가 브로커에 저장될 때까지 블로킹된다. 이를 통해 전송 성공 여부와 파티션, 오프셋 정보를 정확히 확인할 수 있다. 하지만 이 방식은 배치 효과를 크게 떨어뜨린다. 메시지 하나하나를 기다리게 되므로 처리량이 급격히 낮아질 수 있다. 따라서 처리량보다 정확성이 중요한 경우에만 제한적으로 사용해야 한다.

보다 실무에서 많이 사용하는 방식은 Callback을 활용한 비동기 처리다. Callback은 메시지 전송이 완료되었을 때 자동으로 호출되는 함수형 인터페이스다. 이 방식은 블로킹 없이 전송 결과를 확인할 수 있어 프로듀서의 배치 처리 성능을 유지할 수 있다. 성공 시에는 메타데이터를 받고, 실패 시에는 예외 정보를 기반으로 재시도나 기록 처리를 수행할 수 있다. 대부분의 실무 환경에서는 Callback 방식이 기본 선택이 된다.


Kafka 프로듀서 ack 설정

Kafka 프로듀서에서 ack 설정은 메시지 전송 보장 수준을 결정하는 핵심 옵션이다. ack는 프로듀서가 브로커로부터 어느 시점에 응답을 받을지 정의한다. ack=0으로 설정하면 프로듀서는 브로커 응답을 기다리지 않는다. 이 경우 전송 속도는 가장 빠르지만, 메시지가 실제로 저장되었는지 전혀 알 수 없다. 데이터 유실을 감수할 수 있는 경우에만 사용해야 한다.

ack=1은 파티션의 리더 브로커에 메시지가 저장되었을 때 응답을 받는다. 리더에는 저장되었지만 팔로워에 복제되기 전 장애가 발생하면 메시지가 유실될 수 있다. 그래도 많은 서비스에서 기본값으로 사용하는 설정이며, 성능과 안정성 사이의 균형이 비교적 좋은 편이다.

ack=all 또는 ack=-1은 가장 강한 전송 보장 옵션이다. 리더뿐 아니라 설정된 최소 동기화 리플리카(min.insync.replicas) 수만큼 팔로워에 메시지가 저장되어야 성공 응답을 받는다. 이 설정은 데이터 내구성이 매우 높지만, 팔로워 장애가 발생하면 전송 자체가 실패할 수 있다. 결국 ack 설정은 성능과 안정성 중 어디에 더 무게를 둘 것인지에 대한 선택이다.


Kafka 프로듀서 재시도전략

Kafka 프로듀서는 네트워크 오류나 일시적인 브로커 장애에 대비해 재시도 메커니즘을 제공한다. 브로커 응답 타임아웃이나 일시적인 리더 부재와 같은 오류는 재시도를 통해 자연스럽게 복구될 수 있다. 프로듀서는 retries 옵션을 통해 자동 재시도 횟수를 제어할 수 있다.

재시도는 여러 지점에서 발생할 수 있다. send() 메서드 호출 시 예외가 발생하면 예외 타입에 따라 재호출을 고려할 수 있다. 또한 Callback에서 예외를 전달받은 경우에도 정책에 따라 재전송을 수행할 수 있다. 다만 무한 재시도는 매우 위험하다. 특정 메시지가 계속 실패하면 전체 시스템에 부하를 줄 수 있기 때문에 재시도 횟수와 대체 처리 전략을 반드시 함께 설계해야 한다.

재시도 과정에서 주의해야 할 점은 메시지 중복과 순서 보장이다. 브로커 응답이 늦어 재시도가 발생하면 이미 처리된 메시지가 다시 전송될 수 있다. 이를 완화하기 위해 Kafka는 idempotence 옵션을 제공한다. 또한 max.in.flight.requests.per.connection 값을 1로 설정하면 재시도 시 메시지 순서가 뒤바뀌는 문제를 방지할 수 있다. 결국 재시도 전략은 전송 보장, 처리량, 순서 보장 간의 균형을 고려해 설계해야 한다.