13.7.2.1 데이터의 시간적 그룹 결속을 위한 윈도우잉(Windowing) 및 상태 의존(Stateful) 런북

13.7.2.1 데이터의 시간적 그룹 결속을 위한 윈도우잉(Windowing) 및 상태 의존(Stateful) 런북

분산 스트림 처리(Dataflow) 환경에서 수만 개의 센서가 뱉어내는 1밀리초 단위의 텐서 패킷을 하나씩 낱개로 분석하는(Message-by-Message Computing) 짓은 컴파일러의 코루틴 스케줄러를 갈아먹는 학살에 가깝다.
자율주행의 판단 제어나 공장 모터의 진동 분석은 절대 “점(Point) 단위” 데이터로 이루어지지 않으며, “최근 1초간 누적된 1,000개의 진동 벡터 패턴“이라는 면(Surface) 혹은 그룹(Group) 단위로 결속(Binding) 되어야만 딥러닝 모델의 컨텍스트로 편입될 수 있다.

이처럼 무한히 흘러가는 시계열 강물(Stream)을 철저한 도마 위로 올려놓고 1초, 혹은 100개 단위의 사각 상자로 토막 치는(Chopping) 런북을 Zenoh-Flow 에서는 윈도우잉(Windowing) 이라 명명한다. 본 절에서는 시계열 데이터를 묶어 상태(State)를 보존하는 윈도우잉의 수학적 원리와, 기억을 축적하는 상태 의존(Stateful) 오퍼레이터의 설계 지침을 설파한다.

1. Stateless의 한계와 메모리 보존의 철학(Stateful Context)

카메라 원본(Raw Image)을 받아 단순히 흑백(Grayscale)으로 치환하는 노드는 무상태(Stateless) 다. 이전에 들어온 카메라 프레임을 기억할 필요가 전혀 없으며 오직 y = f(x) 수학 원리에 따라 1개의 프레임이 들어오면 1개를 투과시켜 뱉으면 그만이다.

하지만 고도화된 연산, 예를 들어 “최근 5프레임의 좌표를 누적하여 차선의 곡률(Curvature)을 폴리피팅(Poly-fitting)하라” 거나 “지난 5초간의 최고 온도를 산출하라” 라는 지시가 하달되는 순간 연산 오퍼레이터는 과거의 기억 체계(State) 를 강제로 껴안아야 하는 상태 의존적(Stateful) 객체로 돌변한다.

// [단순 무상태(Stateless) 필터와 파멸적 결함]
void Stateless_Node::on_data(Data incoming) {
    // 기억 체계가 없으므로 '누적 합산' 따위를 여기서 연산하는 것은 영원히 불가능하다!
}

Stateful 오퍼레이터 노드 클래스는 내부에 메모리 버퍼 레이어(std::deque, 파이썬 Numpy Buffer)를 멤버 변수로 들고 있어야 하며, 쏟아지는 스트림을 이곳에 적재하고 특정 시간이나 크기가 채워졌을 때(Window Trigger) 한꺼번에 연산 함수를 태우고 배관 뒷단으로 결과를 사출(Publish)하는 상태 스케줄링 머신으로 작동한다.

2. 시간(Time) 기준 대 크기(Count) 기준 분할 윈도우의 차원적 대립

윈도우 상자에 데이터를 잘라 담을 때(Grouping), 그 칼질의 기준선은 두 가지 차원으로 갈라진다.

  1. 카운트(Count) 윈도우:
  • “시간이 얼마나 걸리든 상관없으니, 패킷 10개가 찰 때마다 상자를 포장해라.”
  • 주로 센서의 주파수가 극히 일정하여(예: 60Hz 고정) 크기가 곧 시간을 대변할 수 있을 때, 가장 메모리를 예측하기 쉽고 빠른 스루풋을 자랑하는 물리적 묶음 런북이다.
  1. 타임(Time) 윈도우 (Event Time 기반):
  • “단 1개의 데이터가 들어왔든 1만 개가 들어왔든 묻지 말고, 데이터 캡슐에 찍힌 Event Time 을 기준으로 1초 치 분량이 모이면 무조건 상자를 닫아라!”
  • 지터(Jitter)가 심하거나 센서 발생 주기가 들쭉날쭉할 때 강제된다. 특히 네트워크가 순간적으로 단절되었다가(Network Late) 1000개의 패킷이 버스트(Burst)로 터져 들어왔을 때, 카운트로 자르면 1초 만에 100번의 연산이 무지성으로 발동되지만, 타임 윈도우는 그 1000개를 고요하게 ‘1초의 상자’ 하나로 묶어 결속해 방어해 낸다.

3. 워터마크(Watermark)와 윈도우(Window) 트리거의 결착

이 윈도우잉이 Zenoh-Flow 안에서 궁극적으로 동작하기 위해선, 앞서 설명했던 워터마크 댐 방류 기법(13.7.1.3 참조)과 완벽하게 톱니바퀴처럼 맞물려(Trigger Coupling) 돌아가야만 한다.

1초 윈도우 로직이라 함은, “9시 0분 0초부터 9시 0분 1초” 사이의 데이터를 담아두는 상자다.
그런데 파이프라인에서 9시 0분 1초의 타임스탬프를 가진 센서 값을 받았다고 해서 저 상자의 테이프를 즉각 발라버리고 연산해버리면 파국이다! 아직 네트워크 너머 큐 어딘가 늦게 도착하는(Late) 9시 0분 0.999초 짜리 패킷이 오고 있을 수 있기 때문이다.

윈도우 상자의 뚜껑을 닫고 연산 스레드를 깨우라(Trigger Processing)고 명하는 것은 오직 마스터 타이머가 뱉어내는 Watermark 특수 캡슐(예: 워터마크 9시 0분 2초 도달) 뿐이다. 노드는 “이제 절대로 9시 0분 1초 이전의 데이터는 이 파이프라인 우주에 존재하지 않는다“는 확정 신호(Watermark)를 맞고 나서야, 1초 치로 예쁘게 묶인 윈도우 상자의 봉인(Sealing)을 닫고 안심하며 딥러닝 추론 망으로 집어넣게 된다.
점(Points)의 무한한 파도를 상자(Window Box)라는 블록으로 규격화하고, 워터마크라는 배서(Endorsement)로 지각 패킷을 처형시키는 것. 이 논리가 결박되지 않고서는 분산 스트림 처리의 시계열 무결성은 모래성처럼 허물어진다.