카프카 프로듀서(Producer)는 데이터를 생성하여 카프카 클러스터의 토픽(Topic)으로 전송하는 클라이언트 애플리케이션입니다. 단순히 데이터를 보내는 역할을 넘어, '어떻게' 보내느냐에 따라 전체 데이터 파이프라인의 성능, 안정성, 데이터 무결성이 결정됩니다. 프로듀서의 내부 동작과 핵심 설정을 이해하는 것은 대용량 트래픽 환경에서 발생할 수 있는 다양한 문제를 예방하고 해결하는 데 필수적입니다.
프로듀서가 send() 메서드를 호출하면, 메시지는 즉시 네트워크를 통해 전송되는 것이 아니라 여러 단계를 거치는 정교한 비동기 프로세스를 따릅니다.
ProducerRecord 객체를 생성합니다.byte[])로 변환합니다. key.serializer, value.serializer 설정에 지정된 클래스가 이 역할을 수행합니다.batch.size에 도달하거나 linger.ms 시간이 초과되면 전송 준비가 완료됩니다.프로듀서의 동작을 제어하는 가장 중요한 설정들을 통해 성능과 안정성을 튜닝할 수 있습니다.
batch.size와 linger.ms이 두 설정은 프로듀서의 배치(batch) 동작을 제어하여 처리량(Throughput)과 지연시간(Latency) 사이의 균형을 맞춥니다.
batch.size: 하나의 배치에 담을 수 있는 최대 레코드 크기(bytes). 기본값은 16384 (16KB)입니다.linger.ms: 배치를 보내기 전까지 대기하는 최대 시간(milliseconds). 기본값은 0입니다.linger.ms > 0으로 설정하면, 레코드가 도착해도 즉시 보내지 않고 설정된 시간만큼 대기하면서 추가 레코드를 배치에 포함시키려 시도합니다. 이는 전송 횟수를 줄여 네트워크 오버헤드를 감소시키고 처리량을 향상시킵니다. 하지만 개별 메시지의 지연시간은 늘어나는 트레이드오프가 있습니다.
문제 상황: 대량의 로그를 카프카로 전송하는데, 프로듀서 애플리케이션의 CPU 사용량이 비정상적으로 높고 실제 전송률은 기대에 미치지 못합니다.
원인 분석: linger.ms가 기본값인 0으로 설정되어 있을 가능성이 높습니다. 이 경우, 프로듀서는 메시지가 발생할 때마다 개별적으로 전송을 시도하여 잦은 네트워크 I/O를 유발하고, 이는 CPU 사용량 증가와 처리량 저하로 이어집니다.
해결 방안: linger.ms를 5~100ms 사이의 값으로 설정하고, batch.size를 32KB~64KB로 상향 조정하여 배치의 효율을 높입니다. 이를 통해 전송 요청 횟수를 획기적으로 줄여 시스템 부하를 낮추고 전체 처리량을 개선할 수 있습니다.
acks
acks 설정은 프로듀서가 보낸 메시지에 대해 브로커로부터 얼마나 신뢰도 높은 응답을 받을지 결정합니다. 이는 데이터 유실 방지와 직접적으로 연관됩니다.
| acks 값 | 설명 | 장점 | 단점 | 주요 사용 사례 |
|---|---|---|---|---|
0 |
전송 후 응답을 기다리지 않음 (Fire-and-forget) | 가장 빠른 속도, 최소한의 지연시간 | 네트워크 오류나 브로커 장애 시 메시지 유실 가능성 높음 | 유실되어도 무방한 비주요 지표, 대량의 로그 수집 |
1 |
리더 브로커에 저장되면 응답 받음 (기본값) | 속도와 안정성의 적절한 균형 | 리더가 응답 직후, 팔로워에게 복제 전 장애 발생 시 데이터 유실 가능 | 일반적인 메시징 환경 |
all (-1) |
리더와 모든 ISR(In-Sync Replicas)에 저장되면 응답 받음 | 가장 높은 데이터 내구성, 유실 가능성 최소화 (No Data Loss) | 가장 느린 속도, 높은 지연시간 | 주문, 결제, 회원 정보 등 절대 유실되면 안 되는 핵심 데이터 |
문제 상황: 주문 서비스에서 주문 완료 메시지를 카프카로 전송했음에도 불구하고, 후속 처리 시스템에서 해당 주문이 간헐적으로 누락되는 현상이 발생합니다.
원인 분석: acks 설정이 기본값인 1로 되어 있을 가능성이 높습니다. 리더 브로커가 응답을 보낸 직후, ISR의 팔로워 브로커들에게 데이터를 복제하기 전에 장애가 발생하면 해당 데이터는 유실될 수 있습니다.
해결 방안: acks=all로 설정을 변경하여, 모든 동기화된 복제본에 데이터 저장이 완료된 것을 확인한 후에야 전송 성공으로 간주하도록 합니다. 이를 통해 데이터 유실을 원천적으로 방지할 수 있습니다.
retries와 enable.idempotence네트워크는 불안정할 수 있으며, 일시적인 오류로 메시지 전송이 실패할 수 있습니다. 카프카 프로듀서는 이러한 상황에 자동으로 대처하는 메커니즘을 제공합니다.
retries: 일시적인 오류 발생 시 메시지 전송을 재시도하는 횟수입니다.enable.idempotence: true로 설정 시, 멱등성 프로듀서(Idempotent Producer)로 동작합니다. 재시도로 인해 동일한 메시지가 중복으로 적재되는 것을 방지합니다. (기본값: false, 카프카 3.0부터 true가 기본값으로 변경되는 추세)acks=all, retries > 0, enable.idempotence=true 이 세 가지 조합은 데이터의 유실도, 중복도 없는 정확히 한 번 전송(Exactly-Once Semantics)을 보장하는 가장 강력하고 권장되는 설정입니다.
운영 환경에서 마주칠 수 있는 주요 예외와 그 원인, 해결책을 알아두는 것은 매우 중요합니다.
| 예외 클래스 | 발생 원인 | 대응 방안 |
|---|---|---|
TimeoutException |
브로커로부터 정해진 시간(request.timeout.ms) 내에 응답을 받지 못함. 네트워크 문제, 브로커 과부하 등. |
retries 설정을 통해 자동 재시도. 지속 발생 시 브로커 상태 및 네트워크 점검. |
RecordTooLargeException |
전송하려는 메시지 크기가 브로커의 설정(message.max.bytes)보다 큼. |
메시지 크기를 줄이거나, 브로커와 프로듀서의 최대 메시지 크기 설정을 상향 조정. |
NotLeaderForPartitionException |
리더십 변경으로 인해, 메시지를 보낸 브로커가 더 이상 해당 파티션의 리더가 아님. | 프로듀서 클라이언트가 자동으로 메타데이터를 갱신하고 올바른 리더에게 재전송. 일반적으로 자동 해결됨. |
UnknownTopicOrPartitionException |
존재하지 않는 토픽이나 파티션으로 메시지를 보내려 함. | 토픽 이름이 올바른지 확인. 토픽 자동 생성이 비활성화된 경우, 미리 토픽을 생성해야 함. |