3.8 Zenoh 시각화 환경 구축
네트워크 엔지니어에게 수만 줄의 터미널 텍스트 로그는 분석의 대상이지만, 관제 센터를 지휘하는 운영자에게 그것은 그저 시야를 가리는 노이즈일 뿐이다. 눈에 보이지 않는 거대한 분산 통신망의 정상 작동 여부를 단 1초 만에 직관적으로 판단하게 만드는 유일한 수단은 바로 정밀하게 조율된 대시보드(Dashboard) 시각화이다.
앞선 3.7장에서 우리는 땀방울을 흘려가며 라우터에 메트릭 플러그인을 심고, 5초 주기로 스크래핑을 수행하는 Prometheus 데이터베이스의 심장을 뛰게 만들었다. 이제 이 파편화된 시계열 데이터들을 화려하고 직관적인 그래픽 위젯(Widget)으로 탈바꿈시킬 시간이다.
이 장에서는 글로벌 오픈소스 시각화의 절대 강자인 **Grafana(그라파나)**를 도입하여, Zenoh 네트워크 위를 날아다니는 패킷의 흐름, 토폴로지의 시각적 맵핑(Mapping), 그리고 특정 토픽 페이로드에 대한 실시간 트레이싱 인터페이스를 구축하는 파이프라인의 종착역을 향해 달려간다. 차가운 데이터베이스의 숫자들이 생동감 넘치는 맥박 그래픽으로 변모하는 마법을 경험하라.
1. Grafana 대시보드 설치 및 Prometheus 데이터소스 연결
수집된 시계열(Time-series) 데이터에 생명을 불어넣고 운영자의 뇌로 직행하는 직관적인 인사이트를 만들어 내는 최전선이 바로 Grafana(그라파나)이다. Grafana는 Prometheus가 파편화하여 적재해 둔 데이터들을 아름다운 그래프, 게이지, 열지도(Heatmap)로 변환해 주는 강력한 오픈소스 시각화 플랫폼이다.
이 절에서는 Zenoh 텔레메트리를 시각화하기 위한 백지상태의 캔버스를 구축하고, 앞서 띄워놓은 Prometheus 서버와 신경망을 연결하는 과정을 다룬다.
1.1 Grafana 서버 컨테이너 구동
Prometheus와 마찬가지로, 복잡한 시스템 의존성을 배제하기 위해 Docker를 사용하여 독립된 Grafana 인스턴스를 실행한다. 데이터를 영구적으로 보존하기 위해 로컬 볼륨(Volume)을 마운트하는 것을 잊지 말자.
## Grafana의 설정 및 대시보드 데이터를 저장할 볼륨 디렉터리 생성
mkdir -p ~/zenoh_monitor/grafana_data
## 디렉터리 권한 설정 (Grafana 컨테이너의 기본 유저는 472번)
sudo chown -R 472:472 ~/zenoh_monitor/grafana_data
## Grafana 컨테이너 백그라운드 구동 (기본 포트 3000번)
docker run -d \
--name grafana \
-p 3000:3000 \
-v ~/zenoh_monitor/grafana_data:/var/lib/grafana \
grafana/grafana-oss
초기 구동 후 웹 브라우저를 열고 http://localhost:3000에 접속하면 로그인 화면이 나타난다. 기본 계정 체계인 admin / admin을 입력하여 접속하고, 보안을 위해 즉시 비밀번호를 변경해 둔다.
1.2 Prometheus 데이터소스 연동 (Data Source Configuration)
마치 빈 도화지에 물감이 필요한 것처럼, Grafana가 그림을 그리기 위해서는 데이터를 퍼올 우물이 필요하다. 우리는 3.7.2절에서 구축한 Prometheus 서버를 그 우물(Data Source)로 지정해야 한다.
- Grafana 좌측 사이드바에서 톱니바퀴 아이콘(Configuration)에 마우스를 올리고 Data sources를 클릭한다.
- 파란색 Add data source 버튼을 클릭하고, 가장 첫 번째에 있는 Prometheus를 선택한다.
- HTTP 항목의 URL 필드에 Prometheus 서버의 주소를 입력한다.
- 만약 두 컨테이너가 같은 호스트에서 돌고 있다면, 도커 네트워킹을 고려하여 브릿지 게이트웨이 IP(보통
172.17.0.1또는host.docker.internal)를 사용해야 한다:http://172.17.0.1:9090 - 물리적으로 분리된 서버라면 해당 서버의 IP와 9090 포트를 맵핑한다.
- 페이지 하단의 Save & test 버튼을 누른다.
스크린에 녹색 체크 마크와 함께 “Data source is working“이라는 메시지가 뜬다면, 이제 Grafana가 Zenoh 라우터의 심장 박동(Metrics)을 완벽하게 읽어낼 준비가 끝난 것이다.
1.3 첫 번째 텔레메트리 패널(Panel) 생성 맛보기
연동이 제대로 작동하는지 확인하기 위해, 캔버스에 간단한 그래프 하나를 띄워보자.
- 좌측 메뉴에서 + (Create) 아이콘을 누르고 Dashboard를 선택한 후, Add a new panel을 클릭한다.
- 하단 Query 탭의
Metrics browser입력창에 Zenoh 라우터의 대표적인 메트릭 함수 중 하나인zenoh_router_rx_bytes_total(라우터가 수신한 총 바이트 수)을 입력한다. - 데이터가 단순히 누적되는 것을 방지하고 실시간 유입량(Rate)을 보기 위해, 쿼리를 다음과 같이 수학적으로 변환한다:
rate(zenoh_router_rx_bytes_total[1m]) - 우측 상단의 Apply를 누른다.
축하한다! 이제 여러분의 화면에는 Zenoh 라우터가 1분 동안 처리하는 데이터 수신량이 출렁이는 선 그래프(Line Graph)로 아름답게 렌더링 되고 있을 것이다. 다음 절에서는 이 단편적인 그래프들을 엮어, 전체 네트워크 트래픽을 거시적으로 파악할 수 있는 완전체 뷰어(Viewer)를 구성해 나갈 것이다.
2. Zenoh 트래픽 흐름 및 노드 연결 상태 시각화 뷰어 구성
Grafana와 Prometheus 간의 파이프라인(Data Source) 구축이 완료되었다면, 이제는 관제 센터의 대형 디스플레이에 띄워질 실전용 **마스터 대시보드(Master Dashboard)**를 깎고 다듬을 차례다.
운영자에게 가장 중요한 지표는 무엇일까? 그것은 바로 전체 네트워크의 처리량(Throughput) 한계치가 어떻게 변동하고 있는지, 그리고 현재 백본(Backbone) 라우터에 불시에 끊어지거나 요동치는 클라이언트 세션(Session)이 없는지를 감시하는 것이다. 이 절에서는 이 두 가지 핵심 지표를 담아내는 시각화 뷰어 구성법을 다룬다.
2.1 트래픽 흐름(I/O Throughput) 시각화: 대역폭 모니터링
자율주행차나 드론에서 고해상도 비디오 스트림이 쏟아질 때, 네트워크가 이를 얼마나 쾌적하게 소화하고 있는지 파악하기 위한 초당 바이트 처리량(Bytes/sec) 패널을 만든다.
- 빈 대시보드에서 Add a new panel을 적재한다.
- 우측 상단의 패널 유형(Panel type)을 Time series(선 그래프)로 둔다.
- 쿼리 창에 다음의 PromQL(Prometheus Query Language)을 입력한다.
- 수신량 (RX):
rate(zenoh_router_rx_bytes_total[1m]) - 송신량 (TX):
rate(zenoh_router_tx_bytes_total[1m]) - (팁: 대역폭 아웃바운드(TX) 그래프를 음수로 뒤집어 표현하면 RX와 대칭을 이루는 세련된 미러(Mirror) 차트를 연출할 수 있다. 쿼리를
-rate(zenoh_router_tx_bytes_total[1m])로 표기해 보자.)
- 우측 설정 창 Standard options에서
Unit을Data rate -> bytes/sec로 지정한다. 이렇게 하면 Y축이 자동으로500 MB/s,1.2 GB/s등으로 인간 친화적인(Human-readable) 포맷으로 렌더링 된다.
2.2 노드 연결 상태 시각화: 동적 세션 관리
두 번째로 구성할 패널은 현재 라우터 군집에 달라붙어 있는 클라이언트나 피어(Peer) 노드들의 숫자 변화를 직관적으로 감시하는 Stat(숫자 보드) 방식의 위젯이다.
- 새로운 패널을 추가하고, 패널 유형을 Stat으로 변경한다.
- 이 지표는 누적 값이 아니라 현재 상태를 나타내는 게이지(Gauge) 성격이므로, 쿼리에 단순히
zenoh_router_sessions_active를 입력한다. - 한눈에 상태의 위험도를 파악할 수 있도록 **Thresholds(임계값)**를 설정한다.
- 예: 클라이언트 세션이
0개면 시스템 단절 위험이므로 붉은색(Red). - 세션이 기본 범위를 유지하면 녹색(Green).
- 세션이 비정상적으로 치솟아 라우터의 임계 커넥션(예: 10,000개 이상)을 넘어서 병목이 우려된다면 주황색(Orange)으로 설정한다.
2.3 대시보드 변수(Variables)를 활용한 멀티 라우터 필터링
만약 시스템에 로스앤젤레스, 도쿄, 프랑크푸르트에 배치된 3개의 Zenoh 메인 라우터가 존재한다면 어떨까? 3개의 대시보드를 따로 만들 필요가 없다. Grafana의 Variables 기능을 통해 드롭다운 메뉴로 타겟 인스턴스를 동적으로 필터링하도록 설계해라.
- 대시보드 설정(톱니바퀴 아이콘)에서 Variables로 진입한다.
Query타입으로 변수를 생성하고 이름을instance로 지정한다.- 데이터 소스를 Prometheus로 설정한 후, 쿼리 필드에
label_values(instance)를 입력한다. - 이제 기존에 만들었던 모든 패널의 쿼리를 다음과 같이 변수를 물고 들어가도록 수정한다:
rate(zenoh_router_rx_bytes_total{instance="$instance"}[1m])
모든 설정이 끝나면, 상단의 드롭다운 메뉴를 리모컨처럼 클릭할 때마다 전 세계에 흩어진 Zenoh 라우터들의 트래픽과 연결 상태가 1초의 지연도 없이 마법처럼 눈앞에 펼쳐지는 것을 목격할 수 있다.
3. 분산 네트워크 토폴로지(Topology) 매핑 도구 연동
단순한 꺽은선 그래프와 계기판(Gauge)의 한계는 분산 시스템의 형태, 즉 **토폴로지(Topology)**를 머릿속으로 그려내기 어렵다는 것이다. 무수히 많은 드론, 로봇 팔, 엣지 게이트웨이들이 메쉬(Mesh) 형태로 이리저리 얽혀 통신할 때, 시각적으로 노드와 노드를 선으로 이어주는 **네트워크 노드다이어그램(Node Diagram)**은 병목 구간이나 단절된 가지(Split-brain)를 한눈에 식별하게 해주는 궁극의 모니터링 무기이다.
이 절에서는 앞서 3.7.4절에서 다루었던 Admin Space(@/...) 데이터를 시각적 지도 데이터로 렌더링하기 위한 환경 연동법을 알아본다.
3.1 토폴로지 시각화의 원리와 난제
Grafana는 본래 선형적인 시계열 데이터 파이프라인에 최적화되어 있어, 노드와 링크를 거미줄처럼 이어주는 플로 차트(Flowchart)나 방향성 그래프(Directed Graph)를 기본 패널로 유려하게 그려내기엔 다소 무리가 있다.
이러한 분산 네트워크 매핑을 구현하려면 두 가지 접근법을 고려해야 한다.
- Grafana의 Node Graph Panel 플러그인을 활용하여 노드 간 엣지(Edge) 데이터를 강제로 구겨 넣는 방법.
- Zenoh 생태계 파트너사나 오픈소스 커뮤니티에서 제공하는 전용 토폴로지 뷰어(Topology Viewer) 웹 애플리케이션을 연동하는 방법.
실무 관점에서는 자유도와 직관성이 압도적인 커스텀 웹 뷰어 연동 방식을 채택하는 것이 정석이다.
3.2 Zenoh Admin Space를 활용한 토폴로지 맵 매트릭스 도출
토폴로지를 그리려면 점(Node)과 선(Link)에 대한 좌표를 찍어줄 소위 ’지도 데이터’가 필요하다. 이 데이터는 라우터가 발산하는 주기적인 메트릭이 아닌, 시스템을 동적으로 관통하는 Admin Space 스캔을 통해 획득한다.
별도의 파이썬(Python) 데몬이나 Node.js 백그라운드 워커(Worker)를 두고, 다음과 같이 시스템 상태를 지속적으로 긁어와 웹 클라이언트가 소화하기 편한 JSON 그래프 포맷으로 가공해야 한다.
// 토폴로지 그래프 변환을 위한 추상적인 로직 예시
const graph = {
nodes: [
{ id: "router-A", type: "router", status: "healthy" },
{ id: "drone-1", type: "client", status: "warning" }
],
edges: [
// 라우터 A와 드론 1이 현재 연결(세션)되어 있음을 나타냄
{ source: "router-A", target: "drone-1", protocol: "tcp" }
]
};
3.3 커스텀 토폴로지 매핑 도구 웹 인터페이스 구성
가공된 지도 데이터를 시각적으로 펑펑 터뜨려줄 프론트엔드 엔진으로는 D3.js나 Cytoscape.js와 같은 막강한 그래프 렌더링 라이브러리를 사용한다. 이를 활용해 간단한 정적 웹 서버를 띄워두고 Grafana 대시보드 중앙에 아이프레임(iFrame) 형태로 삽입하는 구성이 가장 깔끔하다.
<!-- 웹 페이지 화면에 뿌려줄 캔버스 공간 -->
<div id="zenoh-topology-map" style="width: 100%; height: 600px;"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.23.0/cytoscape.min.js"></script>
<script>
// 토폴로지 렌더링 엔진 초기화
var cy = cytoscape({
container: document.getElementById('zenoh-topology-map'),
elements: fetchTopologyDataFromAdminSpace(), // 워커가 만들어준 JSON 주입
style: [
{
selector: 'node[type="router"]',
style: { 'background-color': '#ff4d4f', 'shape': 'hexagon', 'label': 'data(id)' }
},
{
selector: 'node[type="client"]',
style: { 'background-color': '#1890ff', 'label': 'data(id)' }
},
{
selector: 'edge',
style: { 'width': 3, 'line-color': '#ccc', 'target-arrow-shape': 'triangle' }
}
],
// 노드들을 우주 배경처럼 퍼뜨려주는 물리 엔진 레이아웃 배치
layout: { name: 'cose', animate: true }
});
</script>
이 매핑 도구가 완성되면, 물리적으로 수천 킬로미터 떨어져 있는 디바이스들이 네트워크상에서는 어떻게 메쉬망을 형성하며 끈끈하게 결합해 있는지, 혹은 특정 라우터가 죽었을 때 트래픽이 어떤 우회 경로로 쏟아져 들어가는지(Routing Tree Change)를 실시간 애니메이션으로 관전할 수 있는 사이버네틱(Cybernetic)한 전지적 시점을 획득하게 된다.
4. 실시간 메시지 페이로드 트레이싱(Tracing) 인터페이스 설정
대시보드를 통해 네트워크 대역폭이 넉넉하고, 토폴로지가 단단하게 연결된 것을 확인했음에도 버그가 터져 로봇이 오작동을 일으킨다면? 이 시점부터는 인프라의 문제가 아니라, 혈관 안을 굴러다니는 적혈구 자체, 즉 전송되는 메시지 페이로드(Payload)의 결함을 심문해 봐야 한다.
실제로 주고받는 데이터의 내용물을 까뒤집어 검사하고 흐름을 역추적하는 **메시지 트레이싱(Message Tracing)**은 애플리케이션 디버깅의 꽃이자 마지막 퍼즐 조각이다.
4.1 Zenoh CLI를 활용한 게릴라식 트레이싱
개발 초기 단계나 신속한 돌발 에러 파악을 위해 터미널 환경에서 가장 무식하면서도 확실한 방법은, 와일드카드(**)를 쥐어짜 내어 네트워크에 흘러 다니는 모든 트래픽의 수문을 열어버리는 것이다.
우리가 개발망에 있다면 다음과 같이 zenoh-cli의 구독(Subscribe) 명령어를 통해 쏟아지는 원시 페이로드를 터미널에 프린트할 수 있다.
## 센서 값과 관련된 모든 계층의 토픽을 감청하여 출력
zenoh sub "robot/sensor/**"
출력 결과:
[robot/sensor/lidar/front] : 124 바이트 수신 -> '{"distance": 1.24, "angle": 45.0}'
[robot/sensor/camera/rgb] : 4096 바이트 수신 -> (Binary Data) ⚠️
하지만, 상용(Production)망에서 초당 수만 개의 메시지가 폭발하는 상황에 이렇게 무차별적으로 덤프(Dump)를 떴다가는 관제 콘솔 자체가 마비될 뿐만 아니라 네트워크 대역폭에 치명적인 부하를 야기한다.
4.2 웹 기반 실시간 메시지 뷰어(Message Viewer) 인터페이스 통합
운영자를 위한 정갈한 인터랙티브 디버깅 환경을 제공하기 위해, 가벼운 웹소켓(WebSocket) 기반의 마이크로 트레이싱 웹 애플리케이션을 띄우는 것이 바람직하다.
이 뷰어 애플리케이션은 관제 센터 내부에서만 접근할 수 있도록 권한이 묶인 상태로 브라우저 상에 렌더링 되며, 사용자가 검색창에 특정 키 경로(예: telemetry/drone/5/*)를 입력할 때만 동적으로 구독(Sub) 세션을 물어 실시간으로 페이로드를 예쁜 표 형태(Table)나 JSON 포맷터 뷰로 파싱(Parsing)해 주어야 한다.
트레이싱 솔루션 구축 파이프라인 지침:
- 백엔드 프록시 구성: Node.js나 Rust로 된 얇은 미들웨어가 Zenoh 네트워크와 웹 브라우저 사이를 중계한다. 브라우저가 직접 Zenoh 패킷을 받는 부하를 줄이기 위함이다.
- 동적 구독 및 페이로드 컨버팅: 사용자가 웹 UI에서 입력한 필터 조건에 맞춰 백엔드 프록시가
zenoh.subscribe()를 수행하고, 수신한 바이너리나 직렬화된 데이터(Protobuf, ROS2 CDR 등)를 인간이 읽을 수 있는 평문 JSON 형태 문자열로 디코딩한다. - 디바운싱(Debouncing) 및 버퍼링: 트래픽이 폭주할 경우 브라우저 렌더링이 멈추지 않도록 초당 화면 갱신 수(FPS)를 조절하는 버퍼 레이어를 웹 프론트엔드에 삽입한다.
이러한 메시지 검침기 레이더가 Grafana 대시보드 옆에 하나 떠 있다면, “현재 온도 센서 값이 왜 영하 100도로 찍히지?“와 같은 소프트웨어 버그를 현장에 엔지니어를 급파하지 않고도 의자에 앉아 1분 만에 색출해 낼 수 있게 된다.