카프카의 설정은 진짜일까?? - offset(3)
- 개발
- 2026. 4. 26. 23:16
지금까지 학습한 내용을 간단하게 정리해보면, offset은 broker에 저장된 메시지의 순서를 의미하고, consumer는 이 offset을 기준으로 메시지를 읽고 처리하게 됩니다.
그리고 어디까지 처리했는지를 기록하는 과정을 offset commit이라고 합니다. 이 commit 방식에는 크게 두 가지가 존재합니다. 자동 commit은 일정 주기에 따라 offset을 자동으로 기록해주기 때문에 구현이 간단하다는 장점이 있습니다. 하지만 처리 완료 여부와 관계없이 offset이 기록되기 때문에, 메시지를 처리하는 도중 애플리케이션에 장애가 발생할 경우 문제가 발생할 수 있습니다.
이 경우 Kafka는 해당 메시지를 이미 처리된 것으로 인식하게 되고, consumer가 재시작되더라도 메시지는 다시 전달되지 않습니다. 결과적으로 데이터 유실이 발생할 수 있습니다.
반면 수동 commit은 개발자가 직접 commit 시점을 제어해야 하기 때문에 다소 번거롭지만,
처리 흐름을 보다 명확하게 관리할 수 있습니다.
자동 commit은 어떻게 하는지 대충 알겠는데 수동 commit은 도대체 어떻게 하는 걸까?
코드를 확인하기 전에 먼저 동작 흐름부터 이해해보겠습니다.
수동 commit은 말 그대로 consumer가 메시지를 처리한 뒤, 개발자가 직접 commit 시점을 결정하는 방식입니다.
consumer는 poll()을 통해 broker로부터 메시지를 가져옵니다. 그리고 가져온 메시지를 바탕으로 비즈니스 로직을 처리한 뒤,
처리가 완료되었다고 판단되는 시점에 commit을 수행합니다.
여기서 주목해야 할 점은 commit 시점을 개발자가 직접 결정할 수 있다는 것입니다.
즉, 자동 commit처럼 일정 주기에 의해 offset이 기록되는 것이 아니라, 처리가 끝났다고 판단한 시점에 직접 offset을 기록할 수 있습니다. 수동 commit은 말 그대로 consumer가 메시지를 처리한 뒤, 개발자가 직접 commit 시점을 결정하는 방식입니다.
그렇다면, 어떻게 처리가 끝났다고 판단할 수 있을까?
이를 이해하기 위해서는 Acknowledgment 개념을 알아야 합니다.
Acknowledgment는 간단하게 말해, 메시지 처리가 완료되었음을 Kafka에 알리는 신호입니다.
consumer는 메시지를 처리한 뒤 Acknowledgment를 호출하게 되며,
이 시점에 commit이 수행되거나 commit이 가능한 상태가 됩니다.

Acknowledgment는 commit 시점을 어떻게 제어하느냐에 따라 다양한 방식으로 동작하며, 내부적으로는 여러 구현체를 통해 처리됩니다. 대표적으로는 RECORD, BATCH, MANUAL 등의 방식이 있으며, 이러한 방식에 따라 commit 시점이 달라지게 됩니다.

어떤 경우에는 메시지를 하나씩 처리한 뒤 commit하는 것이 적절할 수 있고,
어떤 경우에는 여러 메시지를 한 번에 처리한 뒤 commit하는 것이 더 효율적일 수 있습니다.
그렇다면, MANAL방식은 어떻게 사용하는 걸까?

사용하는 방식 자체는 크게 어렵지 않습니다.
acknowledgment.acknowledge();
를 호출하면, consumer가 처리한 offset이 commit됩니다.
즉, broker 입장에서는 이 메시지는 처리 완료되었다고 판단할 수 있게 됩니다.
그렇다면 여기서 한 가지 의문이 생깁니다.
acknowledgment.acknowledge();
couponIssueRequestHandler.handle(event);
처럼 실제 처리 로직인 couponIssueRequestHandler.handle()을 실행하기 전에 commit을 하면 어떻게 될까요?
이 경우 문제가 발생할 수 있습니다.
commit이 먼저 수행되면 Kafka는 해당 메시지를 이미 처리된 것으로 인식합니다.
그런데 그 이후 handle() 실행 중 애플리케이션 장애가 발생한다면, consumer가 재시작되더라도 해당 메시지는 다시 가져오지 않습니다.
결과적으로 처리되지 않은 메시지가 처리된 것으로 기록되어 데이터 유실이 발생할 수 있습니다.
따라서 MANUAL commit에서는 보통 다음 순서가 되어야 합니다.
couponIssueRequestHandler.handle(event);
acknowledgment.acknowledge();
핵심은 단순합니다. commit은 처리 전에 하는 것이 아니라, 처리 완료 이후에 해야 합니다. 다만 commit을 먼저 수행하게 되면,
메시지를 처리하기 전에 이미 offset이 기록되기 때문에 consumer 입장에서의 처리 지연(latency)은 줄어들 수 있습니다.
하지만 이 경우에는 중요한 문제가 발생합니다. 처리 도중 장애가 발생하더라도 해당 메시지는 다시 전달되지 않습니다.
즉, 데이터 유실 가능성을 감수해야 합니다. 따라서 이러한 방식은 정합성보다 처리 속도를 우선하는 경우에만 제한적으로 고려될 수 있습니다.
마무리
다음 시간에는 이번에 알아보지 못한 BATCH와 RECORD에 대해 학습해보겠습니다.
'개발' 카테고리의 다른 글
| 배치 작업시 예외가 발생한다면 어떻게 처리할까? (0) | 2026.05.06 |
|---|---|
| java에서 println()을 사용하면 안되는 이유 (0) | 2026.05.01 |
| 카프카의 설정은 진짜일까?? - offset(2) (0) | 2026.04.22 |
| 웹소켓 vs mq (0) | 2026.04.20 |
| race condition (0) | 2026.04.13 |