가상 DOM(Virtual DOM)이라는 마법

8

발행일: 2025년 04월 28일

조던 워크는 깊은 심연에 빠진 기분이었다. 'UI = f(State)'라는 아름다운 등식은 그의 눈앞에 아른거렸지만, 그것을 현실로 만들 방법은 보이지 않았다. 상태가 바뀔 때마다 UI 전체를 새로 그리는 것은 마치 최고급 스포츠카에 짐마차 엔진을 얹는 격이었다. 아이디어는 빛났지만, 현실의 발목을 잡는 '성능'이라는 족쇄는 너무나 무거웠다.

"DOM… 이 빌어먹을 DOM!"

그는 모니터를 노려보며 으르렁거렸다. 웹 브라우저의 문서 구조 모델(Document Object Model), 즉 DOM은 웹 페이지의 뼈대이자 실체였다. 하지만 이 실체를 건드리는 것은 대가가 컸다. 레이아웃 재계산(Reflow), 화면 재표시(Repaint)… 마치 거대한 관료 조직처럼, 작은 변화 하나에도 복잡하고 느린 절차를 요구했다.

'직접 만지면 느리다… 그렇다면…'

조던의 눈빛이 흔들렸다. 그는 몇 날 며칠을 이 문제에 매달렸다. UI '묘사 객체'를 만드는 것까지는 성공했다. 이전 묘사와 새로운 묘사를 비교해서 '차이점'만 찾아 실제 DOM에 반영해야 한다는 것까지도 알아냈다. 하지만 어떻게? 복잡하게 얽힌 트리 구조의 차이를 매번 효율적으로 비교하는 알고리즘은 그 자체로 또 다른 성능 부담이 될 수 있었다.

"만약… 만약 실제 DOM을 건드리기 전에… 연습을 해볼 수 있다면?"

그의 머릿속에 기묘한 상상이 스쳤다. 마치 중요한 수술 전에 모형으로 예행연습을 하듯, 실제 DOM이라는 '무거운 실체'를 건드리기 전에, 가볍고 빠른 무언가 위에서 먼저 작업을 해보는 것이다.

"그래… 메모리! 자바스크립트 메모리 위에서!"

순간, 그의 온몸에 전율이 흘렀다. 브라우저의 DOM API를 호출하는 것은 느리다. 하지만 순수한 자바스크립트 객체를 메모리 안에서 생성하고 비교하는 것은?

"… 비교할 수 없을 정도로 빠르다!"

마치 막혔던 혈관이 뚫리는 듯한 쾌감! 조던의 손가락이 미친 듯이 키보드 위를 내달리기 시작했다. 그의 머릿속에서 새로운 개념이 형태를 갖추어 갔다.

  1. 가상의 존재: 실제 DOM의 '복사본' 또는 '청사진'에 해당하는 자바스크립트 객체 트리를 메모리 위에 만든다. 이것은 실제 화면과는 아무런 관련이 없는, 순수한 데이터 구조일 뿐이다.
  2. 메모리 위의 전투: 상태가 변경되면, 새로운 상태에 기반한 새로운 가상 DOM 트리를 메모리 위에 생성한다.
  3. 초고속 비교: 이제, 이전의 가상 DOM 트리와 새로 생성된 가상 DOM 트리를 비교한다. 이 비교 작업은 순전히 메모리 안에서 이루어지므로 엄청나게 빠르다!
  4. 최소한의 변화 감지: 비교 알고리즘(Diffing Algorithm)을 통해 두 가상 DOM 트리 사이의 '정확한 차이점'만을 찾아낸다. (예: "이 <span> 태그의 텍스트 내용만 'A'에서 'B'로 바뀌었군.")
  5. 최종 작업 지시: 찾아낸 최소한의 차이점만을 모아서, 딱 한 번, 실제 브라우저 DOM에 적용한다!

"이거다…! 이거야!"

조던은 벌떡 일어섰다. 이것은 마법과 같았다. 개발자는 'UI = f(State)'라는 선언적인 방식에만 집중하면 된다. 상태가 바뀌면 그냥 전체 UI를 새로 그리는 것처럼 코드를 작성한다. 그러면 FaxJS가 내부적으로 이 '가상 DOM'이라는 마법을 부려, 실제로는 변경된 부분만 귀신같이 찾아내어 효율적으로 화면을 업데이트해주는 것이다!

느리고 비싼 실제 DOM 조작은 최소화하고, 빠르고 가벼운 메모리 연산으로 대부분의 작업을 처리한다. 이것이야말로 성능 문제를 해결하면서도 선언적 UI의 우아함을 유지할 수 있는, 두 마리 토끼를 모두 잡는 묘수였다!

그는 이 마법 같은 개념에 이름을 붙였다.

"가상 DOM (Virtual DOM)!"

마치 연금술사가 납으로 금을 만들 듯, 그는 순수한 자바스크립트 객체로 실제 DOM을 조종하는 새로운 연금술의 기틀을 마련한 것이다.

그는 곧바로 이 가상 DOM과 기본적인 비교 로직을 FaxJS 코드에 구현하기 시작했다. 밤을 새워 코드를 짜고, 간단한 예제를 만들어 테스트했다. 1초에 수십 번씩 상태가 변하며 숫자가 증가하는 카운터 애플리케이션. 기존 방식대로라면 브라우저가 버벅거리며 화면이 깨지는 것이 당연했다.

하지만…

// 테스트 실행 결과 (콘솔)
Rendering... Diffing... Patching DOM... (반복)

모니터 위의 숫자는 미친 듯이 빠르게 증가했지만, 화면은 놀랍도록 부드러웠다! 브라우저의 CPU 사용률은 안정적이었다. 가상 DOM이 제 역할을 완벽하게 해내고 있었다.

"됐다…! 됐어!"

조던 워크는 환호성을 질렀다. 오랜 어둠 끝에 찾아온 한 줄기 빛. 아니, 이것은 단순한 빛이 아니었다. 웹 개발의 역사를 바꿀 혁명의 서광이었다. 물론 아직 갈 길은 멀었다. 비교 알고리즘은 더욱 정교하게 다듬어야 했고, 실제 복잡한 UI에서도 잘 작동할지 검증해야 했다.

하지만 가장 중요한 첫걸음, 성능이라는 거대한 벽을 넘을 비책을 그는 손에 넣었다. 코드 네임 FaxJS는 이제 단순한 실험이 아닌, 세상을 바꿀 가능성을 품은 이름이 되었다. 창밖으로 동이 트고 있었다. 새로운 시대의 여명처럼.