💧

실시간 데이터의 '마감 시간' 정하기: 스트림 처리와 워터마크 전략

개요

워터마크 패턴(Watermark Pattern)은 이벤트 스트림 처리에서 사용되는 패턴으로, 이벤트 시간 기반의 스트림 처리 시스템에서 “이 시점까지의 데이터는 모두 도착했다”라고 시스템이 가정하는 임계점(Threshold)를 의미한다. 시스템 성능(지연시간), 데이터 정확성 사이의 트레이드 오프를 관리하는 메커니즘이다.

그래서 워터마크 패턴이 왜 필요한가요?

실제 Computer Vision 업무를 진행하면서 여러개의 카메라에서 ONVIF Metadata를 받아서 처리해야할 일이 있었다. 같은 시간대의 객체와 이벤트들을 가지고 객체를 추적해야 했다. 모든 카메라에 대해 한번에 처리해야했고 이는 굉장히 까다로운 일이었다. 이때 각 카메라에서 100ms 단위로 메타데이터를 쏟아내기 시작하는데 데이터를 수신하는 주체는 카메라와 물리적으로 거리가 있고, 카메라의 네트워크 지연, 성능이슈 등으로 인해 기다리는데에 한계가 존재했다. 따라서 무작정 모든 카메라에서 메타데이터가 도착하기를 기다리는 것은 불가능한 일이었다.

이러한 문제를 해결할 수 있는 방법이 바로 워터마크 패턴이다.

비행기 탑승 게이트

워터마크 패턴을 이해하기 위해 공항의 비행기 탑승 시스템을 예시로 들어보자.

  • 상황: 10:00에 출발하는 비행기가 있다.
  • 승객(데이터 이벤트): 각 승객은 티켓에 적힌 도착 예정 시간이 있다. (이벤트 발생 시간)
  • 실제 도착(처리 시간): 어떤 승객은 9:50에 오지만, 어떤 승객은 차가 막혀 10:02에 게이트에 도착한다. (네트워크 지연)

이때 항공사는 결정을 내려야한다. 10:00 땡 치자마자 문을 닫으면 10:02에 도착한 승객은 탑승하지 못한다. 반대로 모든 승객을 무한정 기다리면 비행기는 영원히 출발하지 못한다. 워터마크는 항공사가 설정한 여유를 둔 마감 기준이다.

현재 시각이 10:10이 되면, 티켓 시간이 10:00인 승객은 더 이상 오지 않을 것이라 간주하고 문을 닫는다.

  • 워터마크 = 10:00 (현재 시각: 10:10): 10시 이전 티켓을 가진 사람은 이제 다 탔다고 선언하는 것

못탄 손님을 어떻게 처리할지 고민이 필요하다. 게이트(워터마크)가 닫힌 후 도착한 승객은 별도 처리(다음 비행기 배정 또는 탑승 거부)해야 한다.

워터마크의 정의

위의 비행기 탑승 게이트 사례에서처럼 스트림 처리를 하다보면 데이터가 네트워크 지연이나 분산 노드의 이슈로 순서가 뒤바뀌어(Out-of-Order) 도착하는 경우가 빈번한다. 워터마크를 이해하려면 두가지 시간을 구분해야 한다.

  • 이벤트 시간(Event Time, TeT_e): 데이터가 실제로 생성된 시간.
  • 처리 시간(Processing Time, TpT_p): 서버가 데이터를 수신하여 처리하는 시간.

워터마크는 다음과 같이 정의할 수 있다.

워터마크 WW가 값 tt를 가질 때, 시스템은 “이벤트 시간 Te<tT_e < t 인 모든 데이터가 이미 도착했다”고 가정한다.

워터마크의 구성요소

워터마크 패턴이 시스템 내에서 논리적인 시계 역할을 수행하기 위해서는 다음 세 가지 핵심 요소가 유기적으로 작동해야 한다.

1. 타임스탬프 추출기 (Timestamp Extractor)

스트림으로 들어오는 데이터 객체에서 이벤트 시간(TeT_e)을 추출하는 컴포넌트다. 패킷이 서버에 수신된 시간이 아니라, 데이터 자체에 포함된 생성 시간을 기준으로 삼는다.

  • 예시: 본인의 업무인 CCTV 영상 분석에서는 패킷 수신 시간이 아닌, ONVIF 메타데이터 헤더에 박혀 있는 utcTimestamp을 추출하여 기준으로 삼는다.

2. 워터마크 생성기 (Watermark Generator)

추출된 타임스탬프를 기반으로 워터마크를 언제, 어떤 값으로 발행할지 결정하는 전략 구현체다.

  • 단조 증가(Monotonically Increasing): 워터마크 시간은 절대 뒤로 가지 않는다. 한 번 10:0010:00라고 선언했으면, 그 다음엔 09:5909:59 워터마크를 발행할 수 없다. 이는 시간의 흐름을 보장하기 위함이다.
  • 발행 전략: 주기적으로(Periodic) 발행하거나, 특정 이벤트가 발생할 때마다(Punctuated) 발행하는 방식이 있다. 보통 Watermark = Max(Event Time) - Lag 공식을 사용하여, 일정 시간(LagLag)만큼의 지연을 허용하는 방식을 사용한다.

3. 지연 처리 정책 (Late Data Policy)

워터마크 라인(임계점)보다 늦게 도착한 데이터를 어떻게 처리할지 정의한 규칙이다. 비즈니스 중요도에 따라 다음 중 하나를 선택한다.

  • 무시(Discard): 가장 간단한 방법. 늦은 데이터는 버린다. (실시간성이 매우 중요한 경우)
  • 로그 기록(Side Output): 메인 스트림 흐름에는 태우지 않고, 별도 스토리지나 로그로 빼서 추후 분석에 활용한다.
  • 허용(Allowed Lateness): 이미 닫힌 윈도우를 일시적으로 다시 열어 결과를 갱신한다. (정확도가 매우 중요한 경우)

워터마크의 처리 프로세스

시스템 내부에서 워터마크는 단순한 숫자가 아니라, 데이터 스트림 사이사이에 삽입되는 특수한 마커(Marker) 패킷처럼 동작한다. 구체적으로 12:00 ~ 12:10 윈도우를 집계하는 상황을 가정해보자.

1. 데이터 유입과 버퍼링

카메라(소스)로부터 데이터가 스트림으로 들어온다. 네트워크 지연으로 인해 순서는 뒤죽박죽이다. 시스템은 들어오는 데이터를 이벤트 시간(TeT_e)을 기준으로 적절한 바구니(Window Bucket)에 분류해 담는다.

  • Data(12:02) 도착 \rightarrow [12:00~12:10] 버킷에 저장
  • Data(12:08) 도착 \rightarrow [12:00~12:10] 버킷에 저장
  • Data(11:59) 도착 (지각생) \rightarrow [11:50~12:00] 버킷에 저장

2. 워터마크 생성 및 전파

소스(Source) 또는 워터마크 생성기는 데이터의 흐름을 보며 주기적으로 워터마크 패킷을 스트림에 흘려보낸다. 보통 가장 최근에 본 이벤트 시간 - 여유 시간(Lag) 공식을 사용한다.

  • 현재 가장 최근 데이터가 12:15이고, 여유 시간을 5분으로 설정했다면?
  • 시스템은 W(12:10) 이라는 워터마크 패킷을 생성하여 데이터 스트림 사이에 끼워 보낸다.

3. 워터마크 수신과 윈도우 트리거

데이터 처리 연산자(Operator)는 계속 데이터를 처리하다가, 데이터가 아닌 W(12:10) 패킷을 만나는 순간 다음과 같이 판단한다.

“워터마크 12:10이 도착했네? 내 약속에 따르면 12:10 이전 데이터는 이제 다 왔어. 더 이상 기다리지 않는다.”

이 순간 시스템은 즉시 [12:00~12:10] 버킷을 닫고(Close), 그 안에 모인 데이터들을 집계(Sum, Count 등)하여 결과를 내보낸다(Emit).

4. 지연 데이터 처리 (예외 상황)

워터마크 W(12:10)이 지나간 뒤에 Data(12:05)가 뒤늦게 도착한다면? 이미 [12:00~12:10] 버킷은 문을 닫고 정산까지 끝냈다. 이 데이터는 지연 데이터(Late Data)로 분류되며, 사전에 설정된 정책에 따라 처리된다. (버려지거나, 별도 로그로 빠지거나, 닫힌 버킷을 다시 열어 결과를 수정한다.)

실제 적용 및 설계 고려사항

워터마크 설정은 정답이 없는 ‘균형 찾기’ 게임이다.

  • 워터마크가 너무 빠르면 (지연 시간 감소): 결과를 빨리 볼 수 있지만, 늦게 도착한 데이터가 버려지거나 별도로 처리되어야 하므로 정확도가 떨어진다. (성격 급한 항공사)
  • 워터마크가 너무 느리면 (정확도 상승): 거의 모든 데이터를 포함하여 정확도는 높지만, 결과를 보는데 너무 오래 걸리며 시스템 리소스를 많이 차지한다. (지나치게 느긋한 항공사)

따라서 지연 데이터(Late Data)를 어떻게 처리할지도 미리 설계해야 한다. 무시할 것인지(Drop), 별도 로그로 뺄 것인지(Side Output), 아니면 이전 결과를 수정할 것인지(Update)는 비즈니스 요구사항에 따라 결정된다.

결론: 완벽함보다는 ‘적시성’

백엔드 개발자로서 익숙했던 RDBMS와 트랜잭션의 세계에서는 데이터의 정합성과 완벽한 순서가 최우선이었다. 하지만 실시간 스트림 처리와 AI 엔지니어링의 세계에서는 허용 가능한 범위 내의 오차적시성이 더 중요한 가치가 되곤 한다.

워터마크 패턴은 무한한 데이터의 흐름 속에서 논리적인 ‘매듭’을 지어주는 도구다. 이를 통해 우리는 불확실한 네트워크 환경 속에서도 신뢰할 수 있는 데이터 파이프라인을 구축할 수 있다.

이 글을 보신 분들이 실시간 데이터 처리시 도움이 되기를 바라면서 이 글을 마친다.

Fred
Fred

백엔드 엔지니어의 시선으로 AI를 해석하고 기록합니다.

대규모 시스템 설계 경험 위에 머신러닝과 LLM을 더해, 실무와 이론의 경계를 넘나드는 엔지니어링 인사이트를 나눕니다.