CSS 박스가 사라지면 무엇이 남는가
CSS로 그래픽 에디터를 만들 때는 도형 하나가 대체로 DOM 요소 하나입니다.
<div class="node" style="transform: matrix(...)"></div>
이 방식은 꽤 편합니다. 브라우저가 layout tree를 들고 있고, DevTools에서 요소를 찍어볼 수 있고, pointerdown 이벤트의 target도 알아서 잡힙니다. z-index를 쓰면 앞뒤 순서도 어느 정도 해결됩니다.
그런데 WebGL이나 WebGPU로 넘어가면 이 편한 것들이 대부분 사라집니다.
DOM node 없음
CSS box 없음
event target 없음
z-index 없음
그려진 픽셀만 있음
처음에는 퇴보처럼 보입니다. 하지만 이게 GPU 렌더러의 출발점입니다. 브라우저가 대신 들고 있던 그래픽 모델을 우리가 직접 들고, 그 모델을 매 프레임 픽셀로 바꿉니다.
CSS 에디터에서 공짜로 받던 것
CSS 기반 에디터에서는 도형을 만들면 브라우저가 많은 일을 대신합니다.
- 요소의 크기와 위치를 계산합니다.
- transform을 합성합니다.
- stacking context를 정리합니다.
- pointer event target을 찾아줍니다.
- DevTools에서 현재 상태를 보여줍니다.
그래서 초반 구현은 빠릅니다. 사각형을 만들고 싶으면 div를 만들면 됩니다. 선택 표시를 그리고 싶으면 outline이나 별도 overlay element를 붙이면 됩니다.
하지만 오브젝트가 많아지고, 복잡한 효과가 늘고, 매 프레임 수천 개의 도형을 부드럽게 움직여야 하면 DOM은 부담이 됩니다. 이때 Canvas/WebGL/WebGPU로 넘어가고 싶어집니다.
문제는 렌더러만 바꾸면 끝나지 않는다는 점입니다.
Canvas에는 도형이 남지 않는다
Canvas에 사각형을 그렸다고 해서 Canvas 안에 사각형 객체가 생기는 것은 아닙니다. 픽셀이 바뀔 뿐입니다.
ctx.fillRect(x, y, width, height);
이 코드를 실행한 뒤 Canvas는 “여기에 사각형이 있었다”는 사실을 모릅니다. 그래서 사용자가 클릭했을 때 어떤 도형을 눌렀는지도 알려주지 않습니다.
WebGL/WebGPU도 마찬가지입니다. GPU는 우리가 보낸 vertex와 shader를 이용해 화면을 그립니다. 하지만 편집기 입장에서 필요한 의미 있는 도형 목록, 선택 상태, 레이어 순서, 잠금 여부, 이름 같은 정보는 GPU가 관리하지 않습니다.
그 정보는 우리가 따로 들고 있어야 합니다.
scene model = 편집기가 이해하는 도형 목록
renderer = scene model을 화면에 그리는 backend
남는 것은 모델이다
CSS 박스가 사라지면 남는 것은 scene model입니다.
const node = {
id: "rect-1",
type: "rect",
x: 120,
y: 80,
width: 200,
height: 120,
rotation: 0,
fill: [0.2, 0.4, 1, 1],
locked: false
};
CSS 에디터에서는 이런 모델이 DOM과 섞이기 쉽습니다. style.left를 읽어서 위치를 확인하고, getBoundingClientRect()로 충돌을 계산하는 식입니다.
GPU 에디터에서는 이 습관을 버려야 합니다. DOM이 진실이 아니라 model이 진실입니다. 렌더러는 model을 읽어서 그릴 뿐입니다.
model -> render
input -> hit test model
edit -> update model
render again
이 흐름이 잡히면 WebGL과 WebGPU는 편집기 전체를 흔드는 거대한 괴물이 아니라, 여러 renderer 중 하나가 됩니다.
오늘의 핵심
GPU 렌더러로 넘어간다는 것은 CSS를 버린다는 뜻이 아닙니다. CSS에서 배운 좌표계, transform, stacking, clipping 감각을 명시적인 모델로 끌어올린다는 뜻입니다.
이번 강의에서 계속 붙잡을 문장은 이것입니다.
DOM이 하던 일을 scene model과 renderer가 나눠서 한다.
도형의 의미는 scene model에 있습니다. 화면에 어떻게 보이는지는 renderer가 담당합니다. 사용자의 입력은 화면 좌표로 들어오지만, 편집은 다시 scene model을 바꾸는 일입니다.
이 분리가 WebGL/WebGPU로 Figma-like 에디터를 만드는 첫 번째 단추입니다.