백엔드 면접 용어 사전
메시지 큐

Exactly-Once

정확히 한 번 처리되는 보장. 브로커만으로는 어렵고 멱등 처리나 트랜잭션과 결합해 달성한다.

정확히 한 번만 처리된다는 보장. 면접에서 가장 오해가 많은 항목이다.

왜 어려운가 — 근본적인 이유

네트워크에서는 "보냈는데 응답이 없다" 는 상황에서 두 경우를 구분할 수 없다.

  • 경우 A: 요청이 도착하지 않았다 — → 다시 보내야 함 경우 B: 도착해서 처리됐는데 응답이 유실 → 다시 보내면 중복

구분이 불가능하므로 재시도는 불가피하고, 재시도가 있으면 중복도 불가피하다. 이것을 "두 장군 문제"라 부르며, 이론적으로 완전 해결이 불가능하다.

그런데 Kafka는 exactly-once를 지원한다는데?

시스템 경계 안에서만 성립한다. Kafka의 EOS(Exactly-Once Semantics)는 read-process-write 패턴, 즉 Kafka에서 읽어 Kafka로 쓰는 흐름에 한한다.

Kafka 토픽 A ──읽기──► 처리 ──쓰기──► Kafka 토픽 B
              └────── 하나의 트랜잭션 ──────┘
                 (오프셋 커밋 + 결과 쓰기를 원자적으로)

두 가지 장치로 구현된다.

  1. 멱등 프로듀서 — 프로듀서마다 ID와 시퀀스 번호를 부여해, 브로커가 중복 쓰기를 걸러낸다
  2. 트랜잭션 — 오프셋 커밋과 결과 메시지 쓰기를 하나의 원자 단위로 묶는다

외부 DB나 외부 API가 끼면 성립하지 않는다. Kafka 트랜잭션이 남의 DB까지 되돌려 줄 수는 없기 때문이다.

실무의 답 — 결과적 exactly-once

  • At-Least-Once (브로커가 보장) — + 멱등 소비자 (내가 구현)
    • = 결과적으로 한 번 처리된 것과 같음

이것을 effectively-once라 부르기도 한다. 실제 시스템에서 말하는 "exactly-once"는 거의 다 이것이다.

면접 답변 골격

"엄밀한 exactly-once는 시스템 경계 안에서만 가능합니다. Kafka는 read-process-write 안에서 트랜잭션으로 제공하지만, 외부 DB·API가 끼면 깨집니다. 그래서 실무에서는 at-least-once + 멱등 처리로 같은 효과를 만듭니다."

이 답변이 "Kafka 쓰면 exactly-once 됩니다"보다 훨씬 좋은 점수를 받는다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 메시지 큐·비동기 — Kafka/RabbitMQ·EOS·순서·outbox