[Kafka] 컨슈머 lag 모니터링: 측정 방법, 늘어나는 원인 진단, 알림 설계
![[Kafka] 컨슈머 lag 모니터링: 측정 방법, 늘어나는 원인 진단, 알림 설계](https://blog.kakaocdn.net/dna/c8vuXm/dJMcai4AgiS/AAAAAAAAAAAAAAAAAAAAAJeVsjYE4lEhB_qL6gCfGwsN4q2BaJiOPXMPBHzzCCp9/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1785509999&allow_ip=&allow_referer=&signature=HDeoSmfIbgxqmm%2BQrqNxlrdilT8%3D)
[Kafka] 컨슈머 lag 모니터링: 측정 방법, 늘어나는 원인 진단, 알림 설계
카프카 컨슈머를 운영하면 가장 먼저 봐야 할 지표가 lag이에요. lag은 컨슈머가 얼마나 뒤처졌는지를 보여주는데, 이 하나로 "지금 잘 돌고 있나, 적체가 쌓이나"를 알아요. lag을 안 보면 컨슈머가 멈춰도 한참 뒤에야 알게 돼요.
lag이 정확히 뭔지에서 시작해 측정하는 방법, 스프링에서 메트릭 노출, lag이 늘 때의 원인 진단, 알림 설계, 자주 만나는 문제 순서로 풀어요. 컨슈머 동작은 @KafkaListener 컨슈머 설정 글을 먼저 보면 좋아요.
01. 컨슈머 lag이란 무엇인가
lag은 아직 처리하지 못한 메시지 수예요. 정확히는 파티션의 마지막 오프셋(log end offset)에서 컨슈머가 커밋한 오프셋을 뺀 값이에요.

lag이 0에 가까우면 들어오는 족족 처리하고 있다는 뜻이고 lag이 계속 커지면 들어오는 속도를 처리 속도가 못 따라간다는 뜻이에요. 즉 lag의 추세가 컨슈머 건강의 핵심 신호예요. 순간값보다 "늘고 있나 줄고 있나"가 더 중요해요.
함정 하나. lag이 0이라고 항상 정상은 아니에요. 프로듀서가 멈춰서 들어오는 게 없어도 lag은 0이거든요. lag은 "처리가 따라가고 있나"만 말해주니, 메시지 유입량(인입 rate)을 같이 봐야 "시스템이 살아 있나"까지 확인돼요.
02. lag 측정하는 법
가장 기본은 카프카가 주는 CLI예요. 컨슈머 그룹의 파티션별 lag을 바로 봐요.
kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group order-service
출력에 파티션별 CURRENT-OFFSET, LOG-END-OFFSET, LAG이 나와요. 어느 파티션의 lag이 큰지까지 보이니 진단의 출발점이에요.
운영에서는 이걸 자동으로 수집해 대시보드에 띄워요. 컨슈머가 내보내는 JMX 지표 records-lag-max를 Prometheus 같은 곳으로 긁거나, Burrow 같은 전용 모니터링 툴을 쓰기도 해요. 핵심은 사람이 CLI를 치지 않아도 lag 추세가 늘 보이게 만드는 거예요.
전용 툴은 단순 숫자 이상을 줘요. 예를 들어 Burrow는 절대 lag 값에 임계치를 거는 대신, lag의 변화 추세를 보고 컨슈머 상태를 OK·WARN·ERR로 평가해요. 트래픽에 따라 lag의 정상 범위가 달라지니, 고정 숫자보다 추세 기반 판정이 오탐이 적거든요. 그룹별로 "따라잡는 중인지, 뒤처지는 중인지"를 자동으로 알려주는 거예요.
컨슈머 그룹 상태도 같이 봐요
같은 CLI로 그룹의 상태도 보여요. 그룹이 Stable이 아니라 PreparingRebalance·CompletingRebalance에 자주 머물면, 리밸런싱이 반복되며 처리가 멈췄다 가는 거예요. lag 숫자만 보지 말고 그룹 상태도 함께 보면 원인이 빨리 좁혀져요.
03. 스프링에서 lag 메트릭 노출
스프링 부트는 Micrometer로 카프카 컨슈머 메트릭을 노출해요. Actuator와 Micrometer를 붙이면 컨슈머의 lag 관련 지표가 메트릭 엔드포인트로 나와요.
# Micrometer가 카프카 클라이언트 메트릭을 수집
management:
endpoints:
web:
exposure:
include: prometheus
metrics:
tags:
application: order-service
그러면 kafka.consumer.fetch.manager.records.lag 같은 지표가 Prometheus로 나가요. 이걸 Grafana에 올려 파티션별 lag 추세를 보고, 임계치를 넘으면 알림을 거는 식이에요.
04. lag이 늘 때, 원인 진단
lag이 계속 늘면 들어오는 속도를 처리가 못 따라가는 거예요. 이때 "전체 lag 합계"만 보면 원인을 못 갈라요. 파티션별 분포부터 봐요.

- 처리가 느림 — 리스너 안의 DB·외부 API 호출이 느린 경우. 가장 흔해요.
- 컨슈머가 부족함 — 트래픽이 늘었는데 컨슈머/파티션이 그대로인 경우. 파티션을 늘리고 컨슈머를 추가해야 해요.
- 파티션 불균형 — 특정 파티션만 lag이 큰 경우. 키 쏠림(hot partition)일 수 있어요.
- 처리가 막힘 — poison pill이 재시도를 무한 반복하며 그 파티션을 막는 경우. 에러 핸들링과 DLQ로 풀어요.
- 리밸런싱 반복 — 컨슈머가 자꾸 추방돼 처리가 멈췄다 가는 경우. 리밸런싱 설정을 점검해요.
전 파티션이 고르게 늘면 처리량 부족, 특정 파티션만 늘면 그 파티션의 쏠림이나 막힘이에요. 이 구분이 진단을 빠르게 해줘요.
05. lag을 줄이는 방법
원인을 찾았으면 줄여야죠. 크게 세 방향이에요.
처리 자체를 빠르게
가장 먼저 볼 건 리스너의 처리 시간이에요. 한 건 처리에 얼마나 걸리는지 측정해서, 느린 DB 쿼리나 외부 API 호출을 개선해요. 건당 100ms가 50ms가 되면 처리량이 두 배가 돼요. 묶어서 처리할 수 있으면 배치 리스너로 DB를 벌크 적재하는 것도 효과가 커요.
컨슈머를 늘리기 (스케일 아웃)
처리를 최적화해도 유입이 더 많으면 컨슈머를 늘려요. 단 @KafkaListener 설정 글에서 봤듯, 동시 처리 컨슈머 수는 파티션 수를 못 넘어요. 그래서 파티션이 부족하면 먼저 파티션을 늘리고 컨슈머를 추가해요.
막힘을 풀기
처리도 빠르고 컨슈머도 충분한데 특정 파티션만 lag이 크면, 그 파티션이 막혔거나 쏠린 거예요. poison pill이 재시도를 반복하는지(에러 핸들링), 키가 한쪽으로 몰리는지(hot partition)를 봐요. 이건 양을 늘려도 안 풀리니 원인을 직접 제거해야 해요.
06. lag과 처리 지연은 달라요
한 가지 구분할 게 있어요. lag(쌓인 건수)과 end-to-end 지연(한 건이 생성돼서 처리되기까지의 시간)은 다른 지표예요.

lag이 0이어도 처리 지연이 길 수 있어요. 메시지가 띄엄띄엄 오면 lag은 늘 0이지만, 한 건을 처리하는 데 오래 걸리면 지연은 커요. 반대로 lag이 커도 빠르게 따라잡는 중이면 곧 회복돼요. 그래서 실시간성이 중요한 시스템은 lag과 함께 "메시지 타임스탬프 기준 처리 지연"도 같이 봐요. 두 지표가 서로를 보완해요.
07. lag 알림 설계
lag 알림은 순간값보다 추세로 거는 게 좋아요. 트래픽이 몰리면 lag은 잠깐 튀었다 금방 줄 수 있거든요. 그래서 "지속적으로 임계치 이상"이나 "계속 증가 중" 같은 조건이 오탐이 적어요.
예를 들어 "lag이 5분 이상 임계치를 넘으면 경고", "lag이 10분 연속 증가하면 경고"처럼요. 처리가 회복되면 lag이 줄어드는지까지 봐야 진짜 문제와 일시적 스파이크를 구분해요.
임계치는 SLO에서 거꾸로 잡으면 좋아요. "메시지를 1분 안에 처리한다"가 목표라면, 분당 유입량을 기준으로 "1분치 이상 쌓이면 경고"처럼 시간으로 환산해요. 절대 건수는 트래픽에 따라 의미가 달라지지만, 시간으로 환산하면 "얼마나 늦어지고 있는가"가 바로 와닿거든요. 토픽마다 중요도가 다르니 임계치도 토픽별로 따로 잡는 게 좋아요.
08. 자주 만나는 문제
lag이 계속 늘기만 해요
처리 속도가 유입 속도를 못 따라가는 거예요. 먼저 리스너 처리 시간을 재보고, 느린 DB·API 호출을 개선하거나 파티션·컨슈머를 늘려요.
특정 파티션만 lag이 커요
그 파티션에 메시지가 쏠리거나(hot partition), poison pill로 막힌 거예요. 키 분배와 에러 핸들링을 점검해요.
lag이 갑자기 0으로 떨어졌어요
오프셋이 리셋됐을 수 있어요. auto.offset.reset이 latest인 상태에서 커밋된 오프셋이 사라지면 끝으로 점프해 lag이 0이 돼요. 이 경우 그 사이 메시지를 건너뛴 거니, 오프셋 관리를 확인해요. "lag이 좋아졌다"가 아니라 "메시지를 잃었다"일 수 있어요.
lag, 이렇게 읽어요
lag은 컨슈머가 얼마나 뒤처졌는지를 보여주는 가장 중요한 운영 지표예요. 파티션의 끝 오프셋에서 처리한 오프셋을 뺀 값이고, 순간값보다 추세가 중요해요. lag이 늘면 분포부터 보고 갈라요.
- 전 파티션이 고르게 늘면 → 처리 속도를 높이거나 컨슈머·파티션을 늘려요.
- 특정 파티션만 늘면 → 키 쏠림(hot partition)이나 막힘을 의심해요.
- 멈췄다 늘기를 반복하면 → 리밸런싱 설정이나 poison pill을 점검해요.
상시 모니터링은 메트릭으로, 빠른 확인은 CLI로 해요. @KafkaListener 설정과 함께 보면 컨슈머를 운영에서 안정적으로 굴리는 그림이 채워져요.
출처: Kafka — Checking Consumer Position (Lag) · Spring Boot — Metrics (Micrometer)
'백엔드 > 메시징' 카테고리의 다른 글
📚 같이 보면 좋은
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 일정액의 수수료를 제공받습니다."