Q1. At-most-once / At-least-once / Exactly-once 차이?
답변
- At-most-once: 재처리를 하지 않기 때문에 중복은 거의 없지만 유실 가능성이 있습니다.
- At-least-once: 재시도와 재읽기를 허용하기 때문에 유실 가능성은 낮추지만 중복 가능성이 있습니다.
- Exactly-once: 프로듀서, 브로커, 컨슈머, 상태 저장소의 경계를 함께 맞춰 중복과 유실을 매우 낮게 관리하지만 설정과 운영 난도가 높습니다.
핵심은 기술 이름보다 어떤 장애에서 무엇을 더 무서워하는가입니다. 결제, 재고, 정산처럼 유실이 더 치명적이면 At-least-once 쪽으로 기울고, 로그 샘플링이나 일부 알림처럼 중복이 더 거슬리는 도메인은 At-most-once도 선택지가 됩니다.
Q2. At-least-once에서 중복은 왜 발생하나요?
답변
대표 케이스는 처리 성공 후 offset commit 전에 장애가 나는 상황입니다. 애플리케이션 입장에서는 이미 DB 반영이나 외부 호출이 끝났지만, Kafka 입장에서는 아직 “이 메시지를 안전하게 끝냈다"는 신호를 받지 못했습니다. 그러면 재시작 뒤 같은 메시지를 다시 읽게 됩니다.
실무 대응은 보통 아래 조합입니다.
- 멱등 키(idempotency key): 같은 이벤트를 여러 번 받아도 한 번만 반영되게 설계
- DB unique constraint: 주문 번호, 이벤트 ID 같은 비즈니스 키 중복 차단
- processed_event 테이블: 처리 이력 기록 후 재처리 여부 판단
- 외부 API 호출 가드: 결제/문자 발송처럼 부작용이 큰 작업은 별도 중복 방지 키 사용
즉, At-least-once는 “중복이 안 생기게 해준다"가 아니라 중복이 생겨도 망가지지 않게 만든다가 더 정확한 설명입니다.
Q3. 순서 보장은 어디까지 되나요?
답변
Kafka 순서는 파티션 단위로만 보장됩니다. 같은 키가 같은 파티션에 들어가고, 그 파티션을 한 소비 흐름이 읽을 때는 순서를 기대할 수 있습니다. 하지만 멀티 파티션 전역 순서는 기본적으로 보장되지 않습니다.
운영할 때는 아래를 같이 봐야 합니다.
- 같은 사용자/주문/계좌처럼 순서가 중요한 키는 항상 같은 파티션으로 라우팅
- 프로듀서 재시도와
max.in.flight.requests.per.connection설정이 순서에 미치는 영향 이해 - 컨슈머 내부에서 비동기 병렬 처리할 때 애플리케이션 레벨 순서 역전이 생기지 않는지 확인
- 재처리 배치나 DLQ 복구 작업이 원래 순서를 깨지 않는지 운영 절차로 관리
Q4. Exactly-once는 언제 진짜 필요할까요?
답변
면접에서 Exactly-once를 말할 때는 “무조건 최고 옵션"처럼 말하면 오히려 위험합니다. 비용과 복잡도가 커서 범위를 좁혀서 써야 합니다.
예를 들어,
- 정산/원장 반영: 같은 이벤트가 두 번 반영되면 금액이 틀어지므로 강한 중복 제어 필요
- 상태 집계 스트림 처리: Kafka Streams 같은 상태 저장 연산에서는 EOS가 실질적 가치가 큼
- 일반 CRUD 동기화: 대부분은 At-least-once + 멱등으로 충분한 경우가 많음
중요한 포인트는 Exactly-once가 시스템 전체의 마법 버튼이 아니라 특정 경계 안에서만 성립한다는 점입니다. Kafka 토픽 내부에서는 EOS를 맞췄더라도, 최종적으로 외부 DB나 서드파티 API 호출까지 완벽히 한 번만 실행된다고 자동 보장되는 건 아닙니다.
Q5. 면접에서 실무형으로 어떻게 말하나요?
답변
아래처럼 정책 → 이유 → 제어장치 → 한계 순서로 답하면 좋습니다.
“저희는 기본적으로 At-least-once를 택했습니다. 유실보다 중복이 덜 위험한 도메인이었고, 소비자에서 멱등 키와 unique constraint로 중복을 흡수했습니다. 순서가 중요한 이벤트는 같은 파티션 키를 사용했고, Exactly-once는 비용이 커서 정산성 집계 같은 일부 흐름에만 제한적으로 검토했습니다.”
이 답변이 좋은 이유는, 단순 정의 암기가 아니라 도메인 리스크를 기준으로 운영 설계를 설명하기 때문입니다.
빠른 선택 기준
| 상황 | 우선 선택 | 이유 |
|---|---|---|
| 로그, 메트릭, 분석 이벤트 | At-most-once 또는 At-least-once | 일부 유실 허용 가능, 운영 단순성이 중요 |
| 주문 상태 변경, 재고 차감, 회원 상태 전환 | At-least-once + 멱등 | 유실이 더 치명적이고 중복은 통제 가능 |
| 정산, 원장, 상태 저장 스트림 집계 | Exactly-once 검토 | 중복 반영 비용이 매우 큼 |
실무 체크리스트
- 이 도메인에서 더 치명적인 것은 유실인지 중복인지 먼저 적었는가?
- 컨슈머 재시작 시 같은 이벤트를 두 번 처리해도 안전한가?
- 외부 API 호출까지 포함하면 어디까지 멱등이 보장되는지 설명 가능한가?
- 순서가 필요한 비즈니스 키를 같은 파티션 키로 묶었는가?
- DLQ 재처리, 수동 재실행, 배치 복구 시나리오까지 운영 문서에 포함했는가?
자주 하는 실수
- Exactly-once를 전체 시스템 보장처럼 말하는 것
- 실제로는 브로커, 클라이언트, 상태 저장소, 외부 시스템 경계를 나눠서 설명해야 합니다.
- 멱등을 코드 한 줄 처리로 보는 것
- 비즈니스 키, 저장 전략, 락, 재시도 정책까지 함께 설계해야 합니다.
- 순서와 전달 보장을 같은 문제로 섞는 것
- 중복 제어와 순서 제어는 관련 있지만 다른 축입니다.
요약
- 전달 보장은 기술 선택이 아니라 도메인 리스크 선택이다.
- 실무 기본은 At-least-once + 멱등 처리 조합이다.
- Exactly-once는 필요한 경계에만 좁게 적용해야 운영 비용을 통제할 수 있다.
💬 댓글