11.6.4.2 Zenoh 메모리 보존을 위한 TRANSIENT_LOCAL 내구성 캐시 회피 및 VOLATILE 강제

11.6.4.2 Zenoh 메모리 보존을 위한 TRANSIENT_LOCAL 내구성 캐시 회피 및 VOLATILE 강제

자율주행 환경에서 sensor_msgs/Image 나 고해상도 PointCloud2 는 매초당 수십 메가바이트씩 터져 나오는 거대한 데이터의 홍수다. 초보 로보틱스 엔지니어들이 QoS(Quality of Service) 설정에서 범하는 가장 파괴적이고 악의적인 실수는 데이터 보존성(Durability) 옵션을 아무 생각 없이 TRANSIENT_LOCAL 로 규정하는 행위다.

로컬 DDS에서 클라우드 관제 데몬까지 뻗어 있는 파이프라인 구간 내에서, 한 장에 3MB인 이미지 스트림에 영속성 캐싱(Durability)을 덮어씌우는 순간, 송신측 데몬과 Zenoh 라우팅 코어의 메모리는 불과 수십 초 만에 Out of Memory(OOM) 한계점까지 팽창하여 커널에 의해 강제 암살당한다. 본 절에서는 대용량 텔레메트리 트래픽의 수명 주기를 파괴하고 메모리 유출을 봉쇄하기 위한 철학, VOLATILE 강제 및 영속성 회피 런북을 설파한다.

1. TRANSIENT_LOCAL의 배신과 메모리 누수(OOM) 궤적

ROS2의 TRANSIENT_LOCAL 내구성(Durability) 옵션은 본래, 뒤늦게 망에 합류한 Subscriber(구독자) 노드라 할지라도, 과거에 전송되었던 데이터를 늦게라도 받을 수 있도록 퍼블리셔(Publisher) 측 메모리 큐(Queue)에 데이터를 악착같이 “저장“해두는 이기적인(Selfish) 보존 옵션이다.
이는 가벼운 상태 값(State, 파라미터 등)을 배포할 때 유용한 철학이다.

그러나 3D LiDAR와 멀티 웹캠 파이프라인에서 이를 가동하면 어떨까?
통신 스레드는 3MB짜리 사진이 나갈 때마다 발송 후 즉각 폐기(Garbage Collection)하는 것이 아니라, 나중에 들어올지도 모를 관전자(Late Joiner)를 위해 거대한 큐 메모리 풀(Pool) 안에 복사본을 유지하려 든다.
만약 history_depth = 10 으로 잡혀 있다면 30MB의 캐시 공간이 강제 할당되며, Zenoh-DDS 브릿지를 통과하는 구간에서는 C++와 Go 진영 두 곳에 이중으로 찌꺼기 메모리가 쌓인다. 이 더미 데이터 핑퐁은 ARM Cortex 기반 엣지 프로세서의 빈약한 RAM 용량을 압살시키고, 커널은 시스템 생존을 위해 OOM-Killer를 발동하여 zenoh-bridge-dds 나 ROS2 노드 데몬을 무참히 학살해버리게 된다.

2. VOLATILE 내구성 선언을 통한 캐시 휘발(Evaporation)

대용량 영상스트림이나 3D 공간 데이터의 설계 원칙에는 오직 하나의 지상 명령만이 존재한다. “과거는 버린다.”
모든 카메라 및 LiDAR 퍼블리셔 코드와, 이를 받아내는 클라우드 UI단 Subscriber 코드는 무조건적으로 내구성 플래그를 VOLATILE 상태로 강제 하향(Downgrade) 변환시켜야 한다.

// [대용량 센서 스트림용 극단적 휘발성 보장 QoS 설정]
rclcpp::QoS volatile_qos_profile(1); // 큐 뎁스마저 1로 극한 압축
volatile_qos_profile.reliability(rclcpp::ReliabilityPolicy::BestEffort);

// 과거의 데이터는 그 어떤 스레드 RAM에도 한 바이트도 남기지 않고 즉각 파기한다.
volatile_qos_profile.durability(rclcpp::DurabilityPolicy::Volatile); 

auto pub = node->create_publisher<sensor_msgs::msg::Image>("/camera/front", volatile_qos_profile);

VOLATILE 선언이 떨어지는 순간, 통신 스택은 한 번 인터넷 라인 밖으로 내뱉은 데이터를 메모리 힙 블록에서 즉시 해제(Free)시켜버린다.
나중에 접속한 태블릿 모니터링 앱이 이전 로봇의 위치 사진을 요구하더라도 ROS2나 Zenoh 라우터는 쿨하게 거절한다. 오직 ’새롭게 생성되어 들어오는 미래의 데이터’만을 퍼날라주는 투명한 배관 파이프로만 동작하게 됨으로써, RAM 점유율 그래프는 영구적으로 수평의 평온함을 그릴 수 있다.

3. 브릿지 데몬 레벨의 QoS Mismatch 대응

문제는 퍼블리셔(로봇)에서 VOLATILE 을 쏘았음에도 불구하고, 수신단인 클라우드 Python 뷰어나 zenohd 설정에서 실수로 TRANSIENT_LOCAL 을 요구할 경우 발생하눈 QoS Mismatch(불일치) 에러다.
이 불일치 현상이 발동되면, 퍼블리셔는 수신 노드를 인정하지 않고 데이터를 아예 보내지도 않는 침묵(Silent Drop)의 강을 건넌다.

따라서 전체 아키텍처 토폴로지에 흩어져 있는 모든 엔드포인트(로봇, 라우터, 브릿지, 클라이언트 앱)는 대용량 스트림에 관하여 단일한 VOLATILE 혈통을 지니도록 하드코딩 되어야 한다.

“대용량 트래픽 통신망의 평화는, 가치 없는 과거 데이터를 메모리상에서 얼마나 신속하고 자비 없이 도살(Slaughter)해 내는가에 달려 있다.” 시스템 메모리 보존(Memory Preservation)의 권능은 무정함에서 탄생함을 잊지 말아야 한다.