상태 저장 스트림 처리와 워터마크 — 늦은 데이터는 어떻게 처리되는가
Apache Spark Structured Streaming 워터마크 공식 문서 및 면접 단골 질문 정리 (웹 리서치, 2026) — Apache Spark 공식 문서(structured-streaming-programming-guide.html) + Databricks 기술 블로그 종합 Spark 공식 Structured Streaming Programming Guide — Watermarking 절
이 모듈을 다 읽으면
- 워터마크가 '얼마나 늦은 데이터까지 결과에 반영할지'를 정하는 임계값이라는 것을 설명할 수 있다
- 워터마크가 상태(state)를 정리하는 원리를 설명할 수 있다
- 세 가지 출력 모드(Append/Update/Complete)와 워터마크의 상호작용을 구분할 수 있다
spark-learn-06/37/38에서 다룬 Structured Streaming 기본을 전제로, 이벤트 시간 기준 집계에서 늦게 도착하는 데이터를 어떻게 다루는지(watermark), 그리고 이게 출력 모드·상태 관리와 어떻게 얽히는지를 정리한다.
withWatermark — '이 정도 늦게 와도 봐준다'는 약속
이벤트 시간(event time, 데이터에 찍힌 실제 발생 시각) 기준으로 윈도우 집계를 할 때, 네트워크 지연 등으로 데이터가 순서 없이 늦게 도착할 수 있다. df.withWatermark('event_time_col', '10 minutes')는 '이 컬럼 기준으로 지금까지 관측한 가장 늦은 이벤트 시간보다 10분 이상 더 늦게 도착하는 데이터는 포기해도 된다'는 임계값을 Spark에게 알려주는 것이다. 즉 워터마크는 '완벽한 정확성'과 '무한정 기다릴 수 없는 현실'(상태를 계속 메모리에 들고 있을 수는 없다) 사이의 타협점을 명시적으로 정하는 장치다.
핵심 포인트
- withWatermark(이벤트시간 컬럼, 지연 임계값)은 '이만큼 늦게 오는 데이터까지는 봐준다'는 명시적 타협점이다
- 워터마크가 없으면 이벤트 시간 기준 집계는 상태를 무한정 들고 있어야 해서 메모리가 계속 증가한다
워터마크가 상태를 정리하는 원리
워터마크는 단순히 늦은 데이터를 거르는 필터가 아니라, 더 이상 갱신될 일이 없는 윈도우의 상태(state)를 안전하게 버려도 된다고 판단하는 기준이 된다. 예를 들어 워터마크가 '지금까지 본 가장 늦은 이벤트 시간 - 10분'을 넘어선 시점이 되면, 그 시점보다 이전에 끝난 윈도우들은 '이제 더 늦은 데이터가 와도 무시할 것'이므로 해당 윈도우의 집계 상태를 메모리에서 제거한다. 이 메커니즘 덕분에 Structured Streaming이 이론상 무한히 계속되는 스트림에서도 상태 크기를 유한하게 유지할 수 있다 — 워터마크가 없다면 모든 윈도우의 상태를 영원히 들고 있어야 한다.
핵심 포인트
- 워터마크를 넘어선(더는 갱신 안 될) 윈도우의 상태는 메모리에서 제거된다 — 상태 크기를 유한하게 유지하는 핵심 메커니즘
- 워터마크가 없으면 무한 스트림에서 모든 윈도우 상태를 영원히 유지해야 해 메모리가 계속 증가한다
출력 모드(Output Mode)와 워터마크의 상호작용
세 가지 출력 모드가 워터마크와 다르게 얽힌다. Append 모드(새로 확정된 행만 출력)는 집계 결과를 기본적으로 지원하지 않는데, 워터마크와 결합하면 '그 윈도우가 워터마크를 넘어 더는 안 바뀔 것이 확실해진 시점'에만 결과를 한 번 출력하는 방식으로 윈도우 집계를 허용한다 — 대신 윈도우가 끝나고 워터마크 지연만큼 더 기다려야 결과가 나온다는 지연이 생긴다. Update 모드(바뀐 행만 출력)는 워터마크 없이도 집계를 지원하지만, 워터마크가 없으면 상태 정리가 안 돼 메모리가 계속 늘어난다. Complete 모드(전체 결과를 매번 출력)는 스트림 시작부터의 모든 레코드를 다 들고 있어야 하는 구조라 상태를 버릴 방법이 없어 워터마크 자체가 지원되지 않는다.
핵심 포인트
- Append 모드: 집계 시 워터마크 필수, 워터마크를 넘어 확정된 시점에만 결과 출력(지연 발생)
- Update 모드: 워터마크 없이도 집계 가능하지만, 없으면 상태가 계속 쌓여 메모리 증가
- Complete 모드: 전체 결과를 매번 출력하는 구조상 상태를 버릴 수 없어 워터마크 미지원
실무 함정 — 지연 임계값을 얼마로 잡을 것인가
워터마크 지연을 너무 짧게 잡으면(예: 1분) 실제로는 정상적인 지연(수 분 늦게 도착하는 흔한 상황)으로 온 데이터까지 '너무 늦었다'며 버려져 집계 결과가 실제보다 적게 나올 수 있다. 반대로 너무 길게 잡으면(예: 1일) 상태를 그만큼 오래 들고 있어야 해서 메모리 사용량이 커지고 결과 확정도 그만큼 늦어진다. 실무에서는 소스 시스템의 실제 지연 분포(대부분의 데이터가 몇 분 안에 도착하는지)를 관찰한 뒤, 그 분포의 꼬리(예: p99 지연)를 감안해 워터마크 값을 정하는 것이 일반적이다.
핵심 포인트
- 워터마크가 너무 짧으면 정상 지연 데이터까지 유실, 너무 길면 메모리 증가+결과 확정 지연
- 실무에서는 소스의 실제 지연 분포(p99 등)를 관찰해 워터마크 값을 정한다