본문 바로가기
1. 개발/1.4. 데이터 분석

Kafka - ack 옵션(0, 1, all)

by 엉짱 2026. 2. 5.
반응형

카프카 프로듀서(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.sizelinger.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을 쓰는 게 답일까요? 아닙니다. 진정한 엔지니어는 "데이터의 가치"에 따라 레버를 조절합니다.

  1. 서비스 운영이 중단될 정도의 데이터인가?acks = all + min.insync.replicas = 2 + batch/linger 튜닝
  2. 일반적인 비즈니스 로그인가?acks = 1 (성능과 안정성의 황금비율)
  3. 데이터가 강물처럼 흘러가도 상관없는가?acks = 0 (미친 속도)

반응형