카프카의 설정은 진짜일까?? - offset(2)

반응형
 

카프카의 설정은 진짜일까?? - offset(1)

원래 시나리오대로면, producer를 전부 끝내고 나서 consumer를 학습하려고 하였지만 살짝 우회하기로 결정하였습니다. 그 이유가 뭐냐면 카프카의 주요 특징중 하나가 offset으로 알고 있습니다. 제

b-programmer.tistory.com

오랜만에 Kafka 관련 글을 작성하게 되었습니다. 이번 글에서는 offset commit에 대해 알아보려고 합니다. Kafka의 offset은 기본적으로 broker에 저장됩니다. 하지만 이 offset을 기준으로 어디까지 처리했는지 관리하는 주체는 consumer입니다. 그 이유는 broker와consumer의 역할이 다르기 때문입니다. broker는 메시지를 저장하고 전달하는 역할을 할 뿐, 우리 서비스의 비즈니스 로직을 직접 수행하지는 않습니다. 실제 메시지를 전달받아 처리하는 쪽은 consumer입니다. 따라서 consumer는 자신이 어디까지 처리했는지 직접 기록할 필요가 있는데, 이 과정을 offset commit이라고 부릅니다. 이번 글에서는 offset commit이 왜 필요한지, 그리고 어떤 방식으로 동작하는지 정리해보겠습니다.

언제, 어떻게 commit이 발생하는지를  직접 확인할 수 있을까?

그 전에 Kafka의 전체 흐름부터 다시 짚어보겠습니다. Kafka는 기본적으로 producer → broker → consumer 구조로 동작합니다.
producer는 메시지를 broker에 저장하고, consumer는 broker로부터 메시지를 가져와 처리합니다.
이때 중요한 포인트가 하나 있습니다. broker에는 메시지가 계속 쌓일 수 있지만, consumer는 그 속도를 따라가지 못할 수도 있습니다.
이렇게 아직 consumer가 처리하지 못한 메시지의 차이를 Kafka에서는 LAG이라고 부릅니다.

LAG와 Commit의 관계

LAG는 다음과 같은 기준으로 계산됩니다.

LAG = LOG-END-OFFSET - CURRENT-OFFSET

여기서 핵심은 두 가지 값입니다.

  • LOG-END-OFFSET
    → broker에 쌓인 마지막 offset
  • CURRENT-OFFSET
    → consumer가 commit한 offset

이 의미를 조금 더 풀어보면 다음과 같습니다. producer는 계속해서 메시지를 broker에 적재하고,
consumer는 메시지를 처리한 뒤 offset을 commit합니다.
이때 consumer의 처리 속도가 producer의 적재 속도를 따라가지 못하거나, commit이 지연되면 두 offset의 차이가 벌어지게 됩니다.  

이 차이가 바로 LAG입니다. 반대로 consumer가 메시지를 처리하고 commit을 진행하면 CURRENT-OFFSET이 증가하면서
LAG는 점점 줄어들게 됩니다.

결국 LAG가 증가한다는 것은 broker에서 consumer로 메시지가 덜 전달되는 것이 아니라,
consumer가 메시지를 충분히 빠르게 처리하지 못해 처리되지 않은 메시지가 누적되고 있는 상태를 의미합니다.

그렇다면 broker로부터 전달받은 메시지는 consumer에서 어떻게 처리될까요?

consumer는 메시지를 단순히 읽는 것이 아니라, 해당 메시지에 대해 비즈니스 로직을 수행하게 됩니다.
하지만 여기서 한 가지 중요한 문제가 있습니다.
Kafka는 메시지를 전달해줄 뿐, 해당 메시지가 실제로 처리되었는지는 알 수 없습니다.
따라서 consumer는 이 메시지까지는 처리 완료했다는 상태를 직접 기록해야 합니다.
이때 사용하는 개념이 바로 commit입니다.

commit은 수동 commit과 자동 commit이 존재합니다. 그렇다면, 수동과 자동으로 왜 분리가 되었을까요?

자동 commit

그 이유는 단순합니다.
언제 처리 완료로 볼 것인가를 누가 결정하느냐의 차이입니다.

자동 commit은 일정 주기마다 offset을 자동으로 commit하는 방식입니다.
consumer는 메시지를 poll로 가져온 이후, 설정된 주기에 따라 offset을 commit합니다.

메시지 조회(poll) → 일정 시간 경과 → 자동 commit

이 방식의 장점은 명확합니다. 구현이 단순하고 별도의 처리 없이도 offset이 관리됩니다.
하지만 치명적인 문제가 존재합니다. 아직 처리가 끝나지 않았는데 commit이 발생할 수 있습니다.
예를 들어 다음과 같은 상황을 생각해볼 수 있습니다.

poll → 메시지 수신
(비즈니스 로직 처리 중)
→ 자동 commit 발생
→ 애플리케이션 장애 발생

 

이 경우 Kafka 입장에서는 이미 해당 메시지가 처리된 것으로 인식하게 됩니다.
따라서 consumer가 재시작되더라도 해당 메시지는 다시 전달되지 않습니다. 결과적으로 데이터 유실 가능성이 발생하게 됩니다.

여기서 말하는 Kafka는 무엇일까요?

기존에 우리가 말하는 Kafka는 broker였습니다. 그렇다면 여기서 말하는 Kafka도 broker일까요?
정확히 말씀드리자면, 여기서 말하는 Kafka는 broker가 아닙니다.
consumer client를 의미합니다.
consumer client는 broker와 분리된 애플리케이션이지만, Kafka 프로토콜을 기반으로 통신하며 동작합니다.

즉, commit은 broker 내부에서 자동으로 처리되는 것이 아니라, consumer client가 주도적으로 수행하는 동작입니다.

이 점이 중요한 이유는 다음과 같습니다.

consumer client는 Kafka broker와 분리되어 있지만, 네트워크를 통해 연결된 상태에서 동작하기 때문에 실행 환경의 영향을 직접적으로 받습니다. 따라서 commit 시점은 항상 안정적으로 보장되는 것이 아니라, 애플리케이션의 상태에 따라 달라질 수 있습니다.

수동 commit

수동 commit은 개발자가 직접 commit 시점을 결정하는 방식입니다.

poll → 메시지 받음 → 처리 완료 → commit

이 방식의 가장 큰 특징은 처리 완료 이후에만 commit을 수행할 수 있다는 점입니다.
따라서 메시지를 처리하기 전에 commit이 발생하는 상황을 방지할 수 있으며, 데이터 유실 가능성을 크게 줄일 수 있습니다.
하지만 그만큼 고려해야 할 점도 존재합니다. 처리가 완료된 이후에 commit을 수행하기 때문에,
commit 이전에 장애가 발생할 경우 동일한 메시지가 다시 전달될 수 있습니다.
즉, 중복 처리 가능성이 발생할 수 있습니다. 또한 commit 시점을 직접 제어해야 하기 때문에, 구현 복잡도가 증가하는 단점도 존재합니다.


오늘은 여기까지 정리해보겠습니다. 이번 글에서는 자동 commit과 수동 commit의 개념을 간단하게 살펴보았습니다. 그렇다면 수동 commit은 개발자가 직접 commit 시점을 제어한다고 했는데, 실제로 어떤 방식으로 처리되는지는 다음 글에서 자세히 다뤄보겠습니다.
또한 consumer가 메시지를 처리할 때 정합성을 우선할 것인지, 처리 속도를 우선할 것인지 이와 관련된 다양한 방법들도 함께 살펴보겠습니다.

 

반응형

'개발' 카테고리의 다른 글

java에서 println()을 사용하면 안되는 이유  (0) 2026.05.01
카프카의 설정은 진짜일까?? - offset(3)  (0) 2026.04.26
웹소켓 vs mq  (0) 2026.04.20
race condition  (0) 2026.04.13
batch - step,job  (0) 2026.04.10

댓글

Designed by JB FACTORY