21.6.4.2 DOM 요소 배제 및 고성능 시각화를 위한 HTML5 Canvas 및 WebGL 프레임워크 도입
React 의 useMemo 를 동원하고 상태를 난도질하여 DOM 노드의 리렌더링을 격리시켰지만(21.6.1.2장 참조), 스웜 로봇의 숫자가 1만 대를 넘어 10만 대의 군집(Swarm) 통제 단위로 넘어가면 궁극적인 물리적 엔진의 장벽에 부딪히게 된다.
아무리 업데이트를 최적화해도 브라우저 내부에 태그 <div> 덩어리 10만 개가 메모리(DOM Tree) 상단에 둥둥 떠 있는 것 자체만으로 브라우저는 질식사한다. 브라우저는 원래 문서(Text)를 그리기 위해 태어난 놈이지, 초점이 1초에 60번 움직이는 수만 개의 점을 그리기 위한 그래픽 엔진이 아니기 때문이다.
본 절에서는 한계에 다다른 고전적 마크업 태그(DOM) 이데올로기를 모조리 불태워버리고, 로봇 10만 대의 시각 통제권을 HTML 의 나약함에서 뽑아내어 GPU 의 병렬 연산력 속으로 처넣어버리는 극한의 렌더링 전이 수술, HTML5 Canvas 2D 및 WebGL 마이그레이션 런북을 갈파한다.
1. DOM 노드의 비극: 리플로우(Reflow)와 리페인트(Repaint)의 폭발
React를 쓰건 Vanilla JS를 쓰건, 관제탑에 로봇 아이콘을 <div class="robot" style="left: 45px; ..."> 식으로 그렸다면 당신은 DOM이라는 저주의 성에 갇힌 것이다.
서버에서 날아온 새 좌표 때문에 left: 45px 가 46px 로 단 1픽셀 변하는 순간, 브라우저 렌더러는 “이 박스 하나가 움직이면 주변 다른 다른 태그들 위치에 영향이 가지 않을까?” 라며 무식하고 정직하게 10만 개 DOM 전체의 레이아웃 위상을 다시 파악하는 연산 (Reflow) 을 쳐버린다.
CPU 팬(Fan)이 비명을 지르고, FPS는 1FPS로 대폭락한다.
2. 태그의 학살 단행과 단일 캔버스(Canvas) 팽창
DOM 이라는 구시대적 틀을 박살 내기 위해, 아키텍트는 저 10만 개의 <div> 태그들을 모조리 척살하고, 브라우저 한가운데 거대한 스케치북인 단 1개의 요소, <canvas id="monitor"> 하나만을 남긴 채 모든 잔해를 치워버린다.
// [Canvas 2D 강제 폭압 드로잉 런북]
const canvas = document.getElementById('monitor');
const ctx = canvas.getContext('2d');
// 매 프레임 그리기 명령이 하달될 때 (예: 방금 Zenoh에서 새 상태가 옴)
function renderAgents(snapshotRobots) {
// 1. 과거의 잔해(이전 프레임)가 남지 않도록 무자비하게 화면을 0픽셀부터 다 쓸어버린다.
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2. DOM 리플로우 따위 없다. 오직 단일 붓의 명령으로 10만 개의 점을 GPU에게 허공에 칠하라 명한다.
for (const [id, odom] of Object.entries(snapshotRobots)) {
const { x, y } = odomToPixel(odom.x, odom.y); // (21.6.4.1장 스케일 방정식)
ctx.fillStyle = '#00ff00';
ctx.fillRect(x, y, 4, 4); // 4x4 크기의 잉크를 DOM 객체 없이 단번에 찍고 빠진다!
}
}
DOM Tree 상에 이 로봇들의 존재는 없다. 오직 브라우저 메모리에 가로세로의 색칠된 픽셀 맵(Bitmap) 배열만이 존재하게 됨으로써, 리플로우(Reflow) 지옥은 무(Zero) 차원으로 수렴한다.
3. 궁극의 포효: WebGL + Shaders GPU 파이프라인 수로 강연
만일 10만 대가 넘어가서 Canvas 2D API 의 CPU 계산력조차 버겁다면? 그 최후의 수단은 브라우저를 벗어나 그래픽 카드의 심장(GPU)을 관통하는 WebGL (또는 Three.js / PixiJS 레이어) 개종이다.
오도메트리 좌표 10만 개의 수열 덩어리(TypedArray)를 CPU 메모리에서 그래픽 카드 VRAM 안으로 던져 넣는다. 그리고 단 한 줄의 병렬 조작 명령 언어(GLSL Vertex Shader)를 작성하여 그래픽 코어 수천 개가 이 점들의 위치를 동시에 타격하여 화면에 쏘게끔(DrawArrays) 강제하는 것이다.
CPU가 루프 10만 번을 도는 짓들을 멈추고, Zenoh 메쉬에서 뽑아져 나온 C++ 바이너리 스트림 배열이 그 원시 형태 그대로 백엔드를 통과해 프론트엔드의 GPU VRAM으로 다이렉트 충돌을 일으키게끔 이음매를 파괴하는 것.
데이터를 문서(Document)로 대우하려는 브라우저의 본성을 찢어버리고, 브라우저를 한낱 백엔드 텐서 배열을 시각 빔(Beam)으로 스캔하는 멍청한 그래픽 출력 터미널(Dumb Terminal)로 전락 시키는 행위. 이것이야말로 10만 엣지 거대 소켓망에서 관제 데스크톱이 OOM 폭사 없이 고유의 프레임 완전 방어 진지를 편성해 내는 최종 전단(Layer)의 무자비한 하드웨어 수직 강하 통치술이다.