Kafka Streams Punctuate — 데이터 시간(STREAM_TIME) vs 시스템 시간(WALL_CLOCK_TIME)
Kafka Streams Punctuate 및 ISR 축소/확장 메커니즘 공식 문서 종합 (웹 리서치, 2026) — Apache Kafka 공식 Javadoc(PunctuationType) + KIP-501 + Confluent 기술 문서 Apache Kafka Javadoc PunctuationType
이 모듈을 다 읽으면
- STREAM_TIME과 WALL_CLOCK_TIME이 punctuate() 호출 시점을 어떻게 다르게 결정하는지 설명할 수 있다
- STREAM_TIME 기준 punctuate가 데이터가 안 들어오면 아예 호출되지 않는다는 함정을 설명할 수 있다
kafka-learn-37에서 다룬 Kafka Streams의 윈도우 연산을 전제로, 그 안에서 '주기적으로 뭔가를 하고 싶을 때'(예: 윈도우 만료 체크, 주기적 집계 flush) 쓰는 Punctuator 콜백이 두 가지 서로 다른 시간 개념 중 무엇을 기준으로 스케줄링되는지를 정리한다.
STREAM_TIME — 데이터가 들어와야만 시간이 흐른다
PunctuationType.STREAM_TIME은 기본적으로 TimestampExtractor가 뽑아내는 이벤트 시간(stream-time)을 기준으로 punctuate()를 스케줄링한다. 이 시간은 오직 실제로 들어오는 레코드의 타임스탬프에 의해서만 전진하므로, 예를 들어 1~60초의 연속된 타임스탬프를 가진 60개 레코드를 10초 간격으로 스케줄한 경우 실제 처리 시간과 무관하게 정확히 6번 punctuate()가 호출된다. 반대로 말하면, 새 데이터가 전혀 안 들어오면 stream-time 자체가 전진하지 않으므로 punctuate()도 전혀 호출되지 않는다 — '주기적으로 반드시 실행돼야 하는' 로직을 STREAM_TIME 기준으로 스케줄하면, 데이터 유입이 멈추는 순간 그 로직도 함께 멈춘다는 게 흔히 놓치는 함정이다.
핵심 포인트
- STREAM_TIME은 TimestampExtractor가 뽑는 이벤트 시간 기준 — 실제 처리 시간과 무관하게 데이터 타임스탬프에 의해서만 전진
- 새 데이터가 안 들어오면 stream-time이 멈춰 punctuate()도 전혀 호출 안 됨 — '주기적 실행'을 기대하고 쓰면 함정
WALL_CLOCK_TIME — 데이터 유무와 무관하게 시스템 시간이 흐른다
반면 PunctuationType.WALL_CLOCK_TIME은 순수하게 시스템 시간(실제 벽시계 시간) 기준으로 동작하며, StreamsConfig의 폴링 간격(POLL_MS_CONFIG)마다 전진한다 — 데이터가 들어오든 안 들어오든 시간은 흐른다. 다만 실제 처리 시간에 따라 호출 횟수가 달라질 수 있다는 점은 주의해야 한다 — 60개 레코드를 20초 만에 처리하면 10초 간격 설정으로 2번 호출되지만, 5초 만에 다 처리해버리면 폴링 간격 자체가 벌어질 시간이 없어 한 번도 호출되지 않을 수도 있다. 즉 WALL_CLOCK_TIME도 '정확히 매 N초마다'를 완벽히 보장하진 않고, 폴링 루프 타이밍에 영향을 받는다.
핵심 포인트
- WALL_CLOCK_TIME은 데이터 유무와 무관하게 시스템 시간(폴링 간격마다) 기준으로 전진 — '주기적 실행'이 목적이면 이쪽이 적합
- 다만 처리 속도가 아주 빠르면 폴링 간격이 벌어질 시간이 없어 예상보다 적게 호출될 수 있음 — 완벽한 '정확히 매 N초' 보장은 아님
같은 프로세서 안에서 여러 개를 동시에 쓸 수 있다
init() 메서드 안에서 ProcessorContext#schedule()을 여러 번 호출하면, 서로 다른 PunctuationType을 가진 여러 개의 Punctuator 콜백을 하나의 프로세서 안에 동시에 등록할 수 있다 — 예를 들어 '윈도우 만료는 STREAM_TIME 기준으로, 메트릭 flush는 WALL_CLOCK_TIME 기준으로' 처럼 서로 다른 목적에 맞는 시간 개념을 각각 적용하는 조합이 가능하다.
핵심 포인트
- init()에서 schedule()을 여러 번 호출해 서로 다른 PunctuationType의 콜백을 한 프로세서에 동시 등록 가능
- 목적별로 다른 시간 개념을 조합(예: 윈도우 만료=STREAM_TIME, 메트릭 flush=WALL_CLOCK_TIME) 가능