Watermark — '언제까지 기다릴지'를 시스템이 어떻게 판단하는가
직관적으로
선생님이 시험 답안지를 걷을 때 "9시까지 낸 것만 인정"이라고 마감을 정하는 것과 비슷하다. 하지만 스트리밍 시스템은 애초에 '몇 시까지가 마감인지'조차 미리 알 수 없다 — 얼마나 늦게 오는 데이터까지 기다려줄지를 시스템이 스스로 추정해서 선언해야 한다. Watermark가 바로 이 '마감 선언'이다.
실제 사례
센서 데이터가 최대 20초까지 지연될 수 있다고 가정하자. 지금까지 관측한 가장 최신 이벤트 시각이 9:00:30이라면, watermark = 9:00:30 − 20초 = **9:00:10**으로 설정된다. 즉 "9:00:10 이전 이벤트는 이제 다 도착했다"는 선언이다. 이후에 9:00:09짜리 이벤트가 와도 "너무 늦었다"고 판단해 별도 처리(늦은 데이터 스트림으로 분기하거나 버림)된다.
정확한 원리
`WatermarkStrategy` 인터페이스는 `TimestampAssigner`(각 레코드에서 이벤트 시간을 뽑아내는 역할)와 `WatermarkGenerator`(그 시각들을 보고 watermark를 만들어내는 역할)를 함께 감싼다. 대표적으로 `WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(20))`처럼 최대 지연 허용치를 지정해 쓴다. Watermark는 실제로 스트림 안을 흐르는 특수한 이벤트이며, **연산자는 자신에게 온 watermark를 완전히 처리한 뒤에야 다음 연산자로 전달**해야 한다는 규칙이 있다 — 이 덕분에 윈도우는 자신의 종료 시각을 넘어서는 watermark가 도착해야 비로소 "완료됐다"고 판단해 결과를 내보낸다. 입력이 여러 개인 연산자(예: 두 스트림을 조인)에서는 **각 입력 watermark 중 최솟값**이 그 연산자의 유효 watermark가 된다 — 한쪽만 빨리 진행해서 다른 쪽 데이터를 놓치는 일을 막기 위해서다.
흔한 오해
"watermark는 정확한 현재 시각을 나타낸다"는 오해가 흔한데, 사실은 **추정치이자 타협**이다. 너무 짧게 잡으면 정상적으로 늦게 온 데이터를 놓치고, 너무 길게 잡으면 그만큼 결과가 늦게 나온다(윈도우가 안 닫히니까) — 정확도와 지연시간(latency)의 트레이드오프라는 게 핵심이다.
확인 문제
지각 허용치를 `forBoundedOutOfOrderness(Duration.ofSeconds(30))`으로 설정했다가, "지각 데이터를 절대 놓치기 싫으니 60분(3600초)으로 늘려버리자"고 한다면 어떤 부작용이 생길까?
Answer Guide
가장 직접적인 부작용은 결과가 최대 60분 지연되어 나온다는 것(윈도우가 watermark가 그만큼 늦게 지나가야 닫히므로). 부수적으로 그만큼 많은 윈도우의 상태를 오래 붙들고 있어야 해 메모리/디스크 사용량도 늘어난다(State Backend에 따라 OOM 위험은 조건부).
흔히 나오는 부분 정답
"상태가 쌓여서 메모리 문제가 생긴다"까지만 답하는 경우가 많은데, 그보다 더 확실하고 항상 발생하는 결과는 '지연시간 증가'다 — 메모리 문제는 State Backend 설정(RocksDB면 디스크로 spill)에 따라 갈리는 조건부 결과라는 점까지 짚으면 완벽하다.