카프카 프로듀서(Producer) 설정의 핵심인 acks 옵션은 사실 '성능(Throughput/Latency)'과 '데이터 안전성(Durability)' 사이의 저울질(Trade-off)을 결정하는 가장 중요한 레버입니다. 이 레버를 어디로 당기느냐에 따라 카프카는 세상에서 가장 빠른 배달부가 될 수도, 세상에서 가장 꼼꼼한 은행원이 될 수도 있죠.

⚙️ acks 옵션: 데이터 확인 도장을 누가 찍을 것인가?
프로듀서가 메시지를 보낸 후, 브로커로부터 "잘 받았다"는 응답(Acknowledgement)을 언제 받느냐에 따라 안정성과 성능이 결정됩니다.
1. acks = 0 (No Acknowledgement): "총알 배송, 확인은 사절"
이 설정은 프로듀서가 메시지를 보내자마자 브로커가 받았는지 확인도 하지 않고 바로 성공으로 간주합니다.
- 메커니즘: 프로듀서는 네트워크를 통해 데이터를 쏘기만 하고 끝냅니다. 브로커가 메시지를 저장하다 서버가 터졌는지, 네트워크 장애로 증발했는지 전혀 신경 쓰지 않습니다.
- 성능: 압도적 최강. 대기 시간이 거의 '0'에 수렴하므로 최대 대역폭을 다 쓸 수 있습니다.
- 안정성: 최악. 데이터 유실이 발생해도 알 길이 없습니다.
- 사용 사례: 데이터가 조금 유실되어도 서비스에 지장이 없는 경우. (예: 1초에 수십만 건 들어오는 센서의 미세한 온도 변화 로그, 단순 클릭 로그 등)
2. acks = 1 (Leader Acknowledgement): "리더만 믿고 간다"
카프카의 기본값(Default)이자 가장 많이 쓰이는 설정입니다. 파티션의 리더(Leader)가 자신의 로컬 로그에 데이터를 기록하면 즉시 응답을 보냅니다.
- 메커니즘: 리더 브로커는 데이터를 받고 자신의 디스크에 쓴 뒤 "오케이, 나 받았어!"라고 신호를 줍니다. 팔로워(Follower)들이 복제해갔는지는 확인하지 않습니다.
- 성능: 균형 잡힌 속도. 리더의 응답만 기다리면 되므로 적절한 속도를 보장합니다.
- 안정성: 보통. 리더가 응답을 주자마자 서버가 폭발하고, 팔로워들이 아직 복제를 못한 상태라면 그 데이터는 유실됩니다.
- 사용 사례: 일반적인 서비스 데이터. 적절한 성능과 꽤 높은 수준의 안정성이 필요한 대부분의 비즈니스 로직.
3. acks = all (또는 -1, All ISR Acknowledgement): "철통 보안, 전원 합의"
가장 높은 안정성을 제공하는 옵션입니다. 리더뿐만 아니라 현재 ISR(In-Sync Replicas) 그룹에 속한 모든 팔로워가 복제를 마칠 때까지 기다립니다.
- 메커니즘: 리더는 데이터를 받고, 모든 팔로워가 "나도 복사 끝났어!"라고 리더에게 신호를 줄 때까지 기다린 후, 마지막에 프로듀서에게 "전원 이상 무!"라고 응답합니다.
- 성능: 가장 느림. 네트워크 왕복(Round-trip) 시간이 늘어나고, 팔로워 중 하나만 느려져도 전체 응답이 늦어집니다.
- 안정성: 최강. 최소한 두 대 이상의 서버(리더+최소 1개 이상의 팔로워)에 데이터가 저장되었음이 보장되므로, 서버 한 대가 물리적으로 파괴되어도 데이터는 살아남습니다.
- 사용 사례: 금융 결제 데이터, 주문 이력, 상폐 직전 주식의 마지막 거래 데이터(?) 등 절대 잃어버리면 안 되는 치명적인 데이터.
🛠️ 성능을 더 짜내기 위한 '전략적 조합'
단순히 acks만 조절한다고 성능이 완성되는 게 아닙니다. 이 옵션들은 아래 설정들과 시너지를 낼 때 진가를 발휘합니다.
① min.insync.replicas와의 조합 (중요!)
acks = all을 설정했더라도, ISR에 리더 혼자만 남아있다면 사실상 acks = 1과 다를 바 없습니다.
- 이를 방지하기 위해 브로커 설정에서
min.insync.replicas = 2를 줍니다. - 이렇게 하면 "리더 포함 최소 2대가 복제를 성공해야 인정해주겠다"는 뜻이 됩니다. 만약 팔로워들이 다 죽어서 리더 혼자 남으면, 카프카는 쓰기 요청을 거절하며 데이터 정합성을 지켜냅니다.
② retries (재시도 전략)
acks를 1이나 all로 두었을 때, 일시적인 네트워크 오류로 응답을 못 받을 수 있습니다. 이때 retries 설정을 통해 자동으로 다시 보내게 해야 합니다. 성능을 위해 acks = 0을 썼다면 재시도 자체가 무의미해집니다.
③ 처리량 극대화를 위한 batch.size와 linger.ms
acks = all 때문에 응답이 늦어지는 게 고민이라면, 메시지를 하나씩 보내지 말고 '뭉쳐서' 보내야 합니다.
batch.size: 한 번에 보낼 데이터 꾸러미의 크기를 키웁니다.linger.ms: 메시지를 바로 보내지 않고 아주 짧은 시간(예: 5ms) 기다렸다가 모아서 보냅니다.- 이렇게 하면
acks = all의 지연 시간을 획기적으로 상쇄하면서도 데이터 안전성을 챙길 수 있습니다.
📊 퀵 비교 테이블
| 구분 | acks = 0 |
acks = 1 |
acks = all |
|---|---|---|---|
| 처리량 (Throughput) | 최고 (Highest) | 높음 (High) | 보통 (Moderate) |
| 지연 시간 (Latency) | 최저 (Lowest) | 낮음 (Low) | 높음 (High) |
| 데이터 안정성 | 없음 (None) | 양호 (Good) | 완벽 (Exceptional) |
| 유실 가능성 | 매우 높음 | 리더 장애 시 발생 가능 | 거의 없음 (클러스터 전멸 시에만 발생) |
💡 결론: "사용자의 선택은?"
"카프카 성능을 더 짜내고 싶어!"라고 하셨죠? 그렇다면 무조건 acks = 0을 쓰는 게 답일까요? 아닙니다. 진정한 엔지니어는 "데이터의 가치"에 따라 레버를 조절합니다.
- 서비스 운영이 중단될 정도의 데이터인가? →
acks = all+min.insync.replicas = 2+batch/linger 튜닝 - 일반적인 비즈니스 로그인가? →
acks = 1(성능과 안정성의 황금비율) - 데이터가 강물처럼 흘러가도 상관없는가? →
acks = 0(미친 속도)
'1. 개발 > 1.4. 데이터 분석' 카테고리의 다른 글
| Kafka - Cleanup Policy: Delete vs Compact (0) | 2026.02.06 |
|---|---|
| Kafka는 어떻게 부하를 분산할까? (Consumer Group) (1) | 2026.02.05 |
| Kafka - 데이터 유실을 막기 위한 'ISR(In-Sync Replicas)' 개념 (0) | 2026.02.05 |
| Kafka 의 핵심 기술인 '제로 카피(Zero Copy)'와 '페이지 캐시' (0) | 2026.02.05 |
| Kafka vs RabbitMQ 어떤 상황에서 Kafka를 선택해야 하는가? (2) | 2026.02.05 |