16.6 네트워크 트래픽 최적화 및 대역폭 절감
초당 1GB 의 데이터를 쏠 수 있는 엄청난 서버를 샀다 한들, 당신의 로봇이 사막 한가운데서 초당 1MB 밖에 다운로드되지 않는 인공위성(Starlink) 망에 묶여 있다면? 물리적인 파이프 확장이 불가능한 경우, 개발자가 취할 수 있는 유일한 수단은 “보내는 짐의 무게 자체를 깎아내는 것“이다.
이 장에서는 데이터를 압축하고, 중복을 제거하며, 쓸데없는 잡음을 소거하여(Silencing) 가장 좁고 고통스러운 네트워크 환경(LoRa, Satellite) 에서도 Zenoh 트래픽이 기적적으로 돌아가게 만드는 극단적 대역폭 다이어트(Bandwidth Diet) 런북을 완성한다.
1. Zenoh 내장 데이터 압축(Compression) 활성화 및 알고리즘 효율성 비교
Zenoh 프로토콜의 위대한 점 중 하나는 텍스트(Payload) 자체를 유저 몰래 압축해서 보내주는 투명한 엔진을 내장하고 있다는 것이다.
1.0.1 [인스펙션] 알고리즘 혈투와 트레이드오프
어떤 압축(Compression) 알고리즘을 켤 것인가? 데이터 특성에 가장 잘 맞는 메스를 골라야 한다.
1. zstd (Zstandard) - 밸런스의 황제
JSON 문자열처럼 반복되는 패턴이 많은 센서 로그를 보낼 때 쓰인다.
100바이트 텍스트를 무려 20바이트로 압축해 내는 괴물 같은 성능(압축률 80%) 을 자랑하면서도 CPU 점유율이 낮다. 클라우드로 보낼 땐 무조건 켜라.
2. lz4 - 비디오 프레임 전용 스피드광
라이다 데이터(Point Cloud) 나 이미 압축된 데이터(H.264) 를 쏠 때, zstd 도 무겁다 싶을 때 쓴다.
압축률은 매우 낮지만(20% 수준), 초당 1GB를 실시간으로 우그러뜨릴 수 있는 미친 압축 및 해제 속도(수백 MB/s) 를 자랑한다.
3. 압축 알고리즘 활성화 런북
// zenohd.json5
transport: {
link: {
// tcp나 quic 통신 시, 스트림 자체를 실시간으로 압축한다.
tcp: { compression: "zstd" }
}
}
주의사항: 이미 영상 코덱으로 압축된 MP4 나 JPEG 데이터를 또 zstd 로 라우터에서 압축하려고 하면, 압축률은 0%인데 CPU 만 불태우는 멍청한 짓이 된다. 이럴 때는 과감히 압축을 꺼야(None) 한다.
2. 게시자(Publisher) 측 델타 인코딩(Delta Encoding) 및 변경 데이터 캡처
센서가 1초에 100번 온도를 측정한다. (25.1도, 25.1도, 25.1도, 25.2도…)
바뀌지도 않은 25.1도 데이터를 굳이 “온도: 25.1도” 라고 네트워크에 100번 쏘는 것은 너무나도 아둔하다.
2.0.1 [Runbook] 침묵의 데이터 스트림 (Change Data Capture)
애플리케이션(Application) 단이나 Zenoh 엔진 단에서 “바뀐 것만 보내는” 델타 인코딩(Delta Encoding) 런북이다.
1. 주기 기반(Periodic) -> 이벤트 기반(Event-driven) 강제 전환
C++ / Rust 로봇 코드 안에 있는 while(true) 루프 안의 put() 을 즉시 고쳐라.
// 나쁜 코드 (초당 무조건 10번 전송)
loop {
let t = get_temp();
zenoh.put("sensor", t).await;
sleep(100ms);
}
// 최적화된 코드 (바뀌었을 때만 전송 = 망 대역폭 점유율 1/1000 로 하락)
let mut last_t = -999;
loop {
let t = get_temp();
if abs(t - last_t) > 0.1 { // 온도가 0.1도 변했을 때만!
zenoh.put("sensor", t).await;
last_t = t;
}
sleep(100ms);
}
2. 구독자의 타임아웃 타협
이렇게 아키텍처를 바꾸면, 수신자(관제탑) 입장에서는 데이터가 안 올 때 “센서가 고장 났나? 온도가 그대로인가?” 판단할 수 없는 공포에 사로잡힌다.
해결책으로, “바뀌면 즉시 쏘되, 변경이 없더라도 최소 10초에 한 번은 무조건 쏜다(Heartbeat)” 는 하이브리드 퍼블리싱 전술을 구사해야 한다.
3. 대역폭 제한(Rate Limiting) 및 트래픽 셰이핑(Traffic Shaping) 적용
에지(Edge) 네트워크, 즉 로봇에 달린 5G 모뎀은 전체 대역폭이 초당 20MB로 고정되어 있다. 여기서 카메라 데이터(19MB/s) 가 선을 넘어서 20MB 를 다 먹어버리면, 정작 로봇의 생명이 걸린 제어 신호(1KB/s) 가 들어갈 파이프조차 막혀 로봇이 통제 불능이 된다.
3.0.1 [Runbook] 물리적 목조르기(Traffic Shaping) 런북
가장 중요한 트래픽을 호위하기 위해, 중요하지 않은 트래픽의 모가지를 강제로 조른다.
1. 리눅스 계층 토큰 버킷 튜닝 (tc 명령어)
Zenoh 자체가 아닌, 라우터가 도는 리눅스의 네트워크 인터페이스(eth0) 밖으로 나가는 트래픽 크기 자체를 칼로 잘라낸다.
## eth0의 대역폭 한계를 초당 15Mbit 로 딱 고정시켜버림!
## 이 명령을 맞은 라우터는 자기가 아무리 빨리 보내려고 해도 커널이 목을 조른다 (Buffer Bloat 강제 유발 및 백프레셔)
tc qdisc add dev eth0 root tbf rate 15mbit burst 32kbits latency 400ms
2. Zenoh 라우터 단기 대역폭 평탄화 (Leaky Bucket)
1시간 평균 대역폭은 10MB 인데, 특정 1초에 데이터가 100MB 가 한 번에 쏟아지는 스파이크(Spike)성 데이터가 가장 위험하다.
이때 Zenoh 의 16.5장에 설명한 큐 사이즈 제한(Queue Length) 과 혼잡 제어(Congestion Control) 를 활용하여, 패킷들을 소켓 버퍼에 한 번에 쑤셔 넣지 않고 마치 수액 링거기(Leaky Bucket) 가 물방울을 떨어뜨리듯 부드럽게(Smooth) 네트워크로 흘려보내는 트래픽 셰이핑(Traffic Shaping) 에 도달해야 한다.
4. 선택적 구독(Selective Subscription) 및 콘텐츠 기반 필터링(Content-based Filtering) 오버헤드 분석
데이터를 그냥 무작정 sub "robot/**" 으로 당겨오는 것은 관제탑 서버를 죽이는 직행 열차다.
4.0.1 [인스펙션] 구독망 정밀 타겟팅 전술
데이터의 종류가 엄청날 때 수신부(Subscriber) 가 대역폭을 아끼는 패턴이다.
1. 와일드카드(Wildcard) 오버 구독의 폐해
관제탑이 sub "**" (모든 걸 구독해) 를 때렸다.
이 순간, 아프리카 사막의 로봇이 쏘는 4K 영상부터 남극 로봇의 라이다 센서 값까지 전 세계 지점의 쓰레기 트래픽들이 꾸역꾸역 라우팅을 거쳐 관제탑 컴퓨터로 밀려들어 온다. 이 관제탑의 인터넷 회선과 Zenoh 수신 스레드(Thread) 는 즉시 터져나간다.
2. 에지 측(Edge-side) 필터링의 우월성
가장 아름다운 아키텍처는 “받아서 버리는 것(Client-side Filtering)” 이 아니라 “가져오기 전에 걸러내는 것(Edge-side Filtering)” 이다.
- 나쁜 구독:
sub "robot/1/sensor"한 다음, 관제탑에서if value > 30이면 경고 띄우기. (이미 데이터가 30도 미만일 때도 태평양 바다를 건너와서 인터넷 종량제 요금을 냈다). - 좋은 구독: 최신 Zenoh 의 고도화된 기능이나 쿼리(Query) 파라미터를 이용해
get "robot/1/sensor?temp>30"형태의 스마트 쿼리를 날리는 것이다. 이렇게 하면 30도가 안 넘는 데이터는 에지 단말 라우터 선에서 전파로 쏘아 올리지도 않고 폐기되므로(Zero Bandwidth), 관제탑의 대역폭은 0 으로 수렴한다.
5. 불필요한 Heartbeat 및 메타데이터 전송 최소화
Zenoh 의 통신 패킷(Payload) 프레임워크를 까보면 개발자가 보낸 10 이라는 숫자(1 Byte) 외에도 부가적으로 붙는 거대한 메타데이터 뼈대(Timestamp, NodeID, SeqNumber 등 최대 40~60 Byte) 가 있다.
5.0.1 [Runbook] 백본 다이어트(Backbone Diet) 전술
위성 통신(Iridium) 처럼 글자 한 자 한 자가 돈(과금) 인 환경에선 메타데이터가 바이러스다.
1. Attachment (사용자 첨부 메타데이터) 금지
Zenoh는 패킷을 보낼 때 유저가 커스텀 라벨을 붙일 수 있다.
// 미친 짓: 1바이트 쏘기 위해 30바이트 문자열을 첨부함.
// 통신 요금 30배 증가!
publisher.put("temp", t)
.with_attachment("format: json, sensor_type: DHT11".as_bytes())
.res()
.await;
첨부 데이터(Attachment) 는 절대로 소위 “설명충” 용도로 쓰면 안 된다. 데이터에 대한 메타 설명은 토픽 이름(Key Expression) 자체의 계층 구조(robot/dht11/json/temp) 에 완전히 녹여 넣어버리거나(URL-encoded), 수신자의 코드 내부에 상수로 맵핑해두어 전파 상에 단 1바이트도 실려 나가지 않게 해야 한다.
2. 통신 인프라 가비지 핑 제거
앞서 세션 구성(16.4) 에서 언급했듯, 라우터가 뱉어내는 유지 핑(Keep-alive Ping) 과 스카우팅(Scouting Multicast) 은 유저 데이터가 아닌 순수한 “낭비 트래픽(Overhead)” 이다.
아키텍트는 극한 환경에서 이 모든 자동 발견(Auto-discovery) 기능을 false 로 죽여버리고, 양쪽 노드의 아이피(IP) 를 하드코딩으로 고정하여 “입 다물고 본론(Payload) 만 이야기하는” 얼음 같은 네트워크 통로(Ice-path) 를 직조해 내야 한다.