콘텐츠로 바로가기

Virtual DOM Reconciliation

[Placeholder for technical implementation]

Article
M

Me

hyunyoun's Blog

web-emerging-technologieswebemerging-technologiesmodern-webframework-physicsvirtual-dom-reconciliationmodern-web-framework-physicsruntimes8 min read

1. Overview

가상 DOM 렌더링 물리(Virtual DOM Reconciliation Physics)는 자바스크립트 엔진이 브라우저의 무거운 실제 DOM(문서 객체 모델)을 직접 비틀어 화면을 그릴 때 발생하는 치명적인 성능 병목(Layout Thrashing)을 회피하기 위해, 메모리 위에 가짜 복사본(Virtual DOM)을 띄우고 두 트리의 차이점만 찾아내 실제 화면에 '패치(Patch)'하는 선언형 UI의 극의를 다룹니다.

과거 제이쿼리(jQuery) 시절, 데이터를 바꾸려면 HTML 뼈대를 하나하나 찾아서 텍스트를 끼워 넣는 수동 조립(Imperative)을 해야 했습니다. React는 "그냥 화면 전체를 매번 다 버리고 새로 그리자"라는 미친 발상을 제시했고, 이를 60fps로 실현하기 위해 O(N3)O(N^3)의 트리 비교 알고리즘을 휴리스틱으로 O(N)O(N)까지 압축해버린 디핑(Diffing)과 재조정(Reconciliation) 물리를 만들어냈습니다. 학습자는 React의 렌더링 사이클이 언제 멈추고 언제 터지는지, 메모리 누수와 리렌더링 폭포(Rerender Waterfall)를 제어하는 렌더링 최적화 방어선을 구축합니다.

2. Scope & Boundaries

In-Scope

  • 가상 DOM 구조: 메모리 트리 렌더링 메커니즘, Fiber Architecture, 더블 버퍼링(Double Buffering) 비유.
  • Diffing & Reconciliation: 트리 비교 알고리즘 휴리스틱(O(N)O(N)), key의 물리적 식별자 역할, 컴포넌트 마운트/언마운트.
  • 렌더링 방어선: 불변성(Immutability), 참조 동등성(Reference Equality), React.memo, useCallback.
  • 브라우저 렌더링 연계: Virtual DOM 패치 후 발생하는 진짜 브라우저 레이아웃(Reflow)과 페인트(Repaint) 병목 통제.

Out-of-Scope

  • 상태 관리 라이브러리 심층 비교: Redux, Zustand, Recoil의 상태 투사(Projection) 패턴 ightarrow ightarrow 14-02-03. State Projections (Signals) 영역으로 위임.
  • 서버 컴포넌트와 하이드레이션: 서버에서 렌더링을 끝내고 내려오는 차세대 렌더링 구조 ightarrow ightarrow 14-02-02. RSC & Hydration Dynamics 영역으로 위임.

Boundaries

  • V-DOM vs 브라우저 DOM (14-02-01 vs 14-01-02): 브라우저 DOM 렌더링(14-01-02)은 화면에 네모 박스를 그리기 위해 C++ 엔진이 수식을 계산하는(Reflow) 무거운 물리 엔진이라면, Virtual DOM(14-02-01)은 그 무거운 엔진의 스위치를 되도록 적게(Batch) 누르기 위해 자바스크립트 뇌가 메모리 안에서 머리를 굴리는 수학적 '예측기'입니다.

3. Counterexample

  • 직접 DOM 조작의 환상 (Imperative Mutation Fallacy): React 안에서 document.getElementById('box').style.color = 'red'를 섞어 쓰는 무지. 가상 DOM은 자기가 쥐고 있는 설계도(메모리)와 브라우저의 실제 화면이 똑같다고(Sync) 믿고 연산하는데, 개발자가 몰래 브라우저 화면을 바꿔버리면 다음 렌더링 틱에 가상 DOM이 패치(Patch)를 할 때 DOM 트리 참조가 엇갈려 앱이 크래시(Crash)되거나 상태가 증발합니다.
  • 배열 인덱스 키의 비극 (Index Key Fallacy): 리스트 요소를 그릴 때 key={index}를 부여하는 습관. 만약 0,1,2번 아이템 중 0번을 삭제하면, 1번이 0번 자리에 오면서 가상 DOM은 "아, 아이템이 삭제된 게 아니라 0번의 글씨가 바뀌었네"라고 착각(휴리스틱 오류)하여 엉뚱한 애니메이션을 재생하거나 입력창(Input) 안의 글자를 뒤섞어버리는 물리적 붕괴가 발생합니다.

4. Prerequisites

  • 브라우저 렌더링 기초 (Basic): 브라우저가 DOM 트리를 조작할 때 Reflow와 Repaint가 왜 느린지 알아야 가상 DOM의 필요성을 느낄 수 있습니다. (14-01-02. Browser Rendering Physics)
  • 자바스크립트 객체와 참조 (Recommended): 불변성(Immutability)과 메모리 주소(Reference) 비교를 알아야 얕은 비교(Shallow Compare)의 렌더링 커트를 이해합니다. (14-01-01. JS Runtime & V8 Engine)

5. Learning Map

Sequence Core Cluster Objective & Description Evidence (BoK)
1 V-DOM Architecture 브라우저 DOM을 건드리는 짓이 왜 느린지 분석하고, 메모리 위에 띄운 가상 객체(V-DOM) 설계도를 구경합니다. Primary
2 Diffing Heuristic 10만 개의 노드를 다 비교하려면 100년이 걸리므로(O(N3)O(N^3)), 같은 층계(Level)만 훑고 지나가는 야매(O(N)O(N))를 배웁니다. Primary
3 The Power of Key 리스트를 찢고 붙일 때 V-DOM 엔진이 요소를 잃어버리지 않게 목줄(key)을 채우는 고유 식별자 물리를 익힙니다. Industry
4 Immutability & Memo 가상 DOM이 트리 비교를 할 때 속도를 높이기 위해, 내용물 대신 메모리 주소표(참조)만 슬쩍 보고 넘기는 방어를 칩니다. Primary

6. Learning Topics

Basic

Core Topic 01: 가상 DOM(Virtual DOM)과 더블 버퍼링 물리

  • Why to Learn: 100개의 데이터를 지우고 다시 그릴 때 브라우저 화면이 100번 깜빡이는 끔찍한 병목을, 메모리 연산 1번으로 압축해 내기 위함입니다.
  • What to Learn: Virtual DOM (메모리 트리), Real DOM, Batch Update(일괄 처리), Double Buffering.
  • How to Learn: 영화를 찍을 때 세트장을 100번 고치는 게 아니라, 뒤에서 똑같은 세트장(V-DOM)을 만들어 다 꾸민 뒤 커튼(Patch)만 한 번에 쓱 열어젖히는(Batch) 선언적 렌더링 뷰 모델을 도식화합니다.
  • Implement: 1초에 10,000번 setState를 호출하더라도 화면 렌더링 횟수는 브라우저의 1틱(약 16ms)에 맞춰 단 1번만 발생하는 리액트의 상태 일괄 묶음(Batching) 병합 메커니즘을 렌더링 로그로 증명.

Core Topic 02: 디핑(Diffing) 알고리즘과 O(N)O(N) 휴리스틱

  • Why to Learn: V-DOM의 과거 트리와 미래 트리를 비교할 때, 완벽한 수학적 알고리즘을 돌리면 너무 느려지므로 리액트가 선택한 실용적인 타협안을 이해하기 위함입니다.
  • What to Learn: Reconciliation(재조정), O(N3)O(N^3) to O(N)O(N) Heuristic, Level-by-level comparison, Type Change(Unmount).
  • How to Learn: 리액트가 1) 부모 태그가 <div>에서 <span>으로 바뀌면 자식까지 전부 부숴버리고 새로 그림(타입 룰) 2) 동일 레벨의 노드만 비교하고 대각선 비교는 안 함(깊이 룰)이라는 무자비한 2대 원칙을 통해 속도를 방어하는 한계선을 추적합니다.
  • Implement: 컴포넌트 A 내부에서 다른 타입의 컴포넌트 B로 렌더링을 분기(if)했을 때, 그 밑에 달린 100개의 자식 노드가 변경되지 않았음에도 전부 파괴(Unmount)되고 다시 생성(Mount)되는 불필요한 렌더링 낭비 구간 재현.

Core Topic 03: 리스트 렌더링과 Key의 식별자 물리학

  • Why to Learn: 게시판 리스트에서 2번 글을 삭제했는데, 엉뚱하게 3번 글의 사진이 날아가는 리액트 특유의 DOM 재사용(Recycle) 오작동을 막기 위함입니다.
  • What to Learn: key Prop, Identity, Element Repositioning, Index Key vs Unique ID.
  • How to Learn: 부모가 리스트 아이템의 순서를 바꿀 때, V-DOM은 내용물을 보지 않고 노드의 고유한 이름표(key)만 보고 위치를 추적합니다. 이때 인덱스(0,1,2)를 주면 V-DOM 엔진이 데이터 이동을 추적하지 못하고 껍데기만 덮어씌워 내부 상태(State)가 꼬이는 참사를 분석합니다.
  • Implement: <input> 태그를 가진 할 일(Todo) 리스트를 렌더링하고, 배열의 인덱스를 key로 썼을 때 중간 아이템을 삭제하면 input 안의 텍스트가 위아래로 밀려버리는 버그를 재현한 뒤, 유니크 ID 값으로 교체하여 디핑(Diffing)을 정상화하는 튜닝 코드 구축.

Core Topic 04: 불변성(Immutability)과 참조 동등성(Reference Equality) 방어

  • Why to Learn: 데이터가 수만 개인 표(Table) 컴포넌트에서, 버튼 하나 눌렀다고 수만 개의 셀을 전부 비교(Diffing)하느라 앱이 멈추는(Jank) 렌더링 폭포를 차단하기 위함입니다.
  • What to Learn: Immutability, React.memo, Shallow Compare(얕은 비교), useMemo, useCallback, Object.is.
  • How to Learn: V-DOM이 자식 컴포넌트로 내려가는 프롭스(Props) 객체의 내용물을 일일이 뜯어보지 않고, 메모리 주소표(참조 포인터)가 바뀌었는지만 O(1)O(1) 속도로 비교(Shallow Compare)하여 같으면 디핑 자체를 건너뛰는(Memoization) 커팅 방어막을 칩니다.
  • Implement: React DevTools Profiler를 켜고, 부모 컴포넌트의 빈번한 상태 변경 시 하위 무거운 차트 컴포넌트가 불필요하게 렌더링되는 지점을 React.memo와 원시값(Primitive)/참조값(Reference) 캐싱(useMemo)으로 썰어내어(Bypass) 렌더링 시간을 10ms 이하로 압축.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
Virtual DOM 브라우저 화면(Real DOM)을 직접 만지면 너무 느리므로, 자바스크립트 메모리에 띄워놓고 맘대로 뜯어고치는 가벼운 UI 복사본입니다. 기본 렌더링 캐시 Real DOM, Fiber vs. Svelte (컴파일러) V-DOM이 무조건 빠르다는 맹신 (메모리와 연산 비용이 들음) Primary core
Reconciliation (재조정) 1초 전의 가상 DOM 트리와 방금 바뀐 가상 DOM 트리를 겹쳐보고, 틀린 그림(차이점)만 찾아내어 브라우저에 명령을 내리는 비교 공정입니다. 실무 트리 비교 Diffing vs. DOM 덮어쓰기 렌더링이 곧 화면 그리기라는 오해 (재조정은 그냥 연산일 뿐임) Primary core
key Prop 리스트 배열을 다룰 때, V-DOM 엔진이 컴포넌트를 잃어버리지 않고 이사(이동) 궤적을 쫓아갈 수 있게 달아주는 고유한 전자발찌입니다. 권장 식별자 Array Map, Index vs. ref (DOM 참조) key에 배열의 순번(index)을 넣어도 아무 문제 없다는 치명적 오류 Industry Docs core
Immutability (불변성) 객체의 내용을 뜯어고치지 않고(A.name='kim'), 아예 새로운 껍데기 박스(B={name:'kim'})로 덮어씌워 V-DOM이 박스 주소만 보고 0.1초 만에 변화를 알아채게 하는 법칙입니다. 실무 상태 관리 React.memo vs. Mutable Object 리액트가 메모리 주소 안의 내부 값까지 친절히 딥 디핑(Deep Diffing)해준다는 오해 Primary core

8. References

Primary References

  • [CS2023: Software Engineering / HCI] — 선언적(Declarative) UI 패러다임, 트리 구조 렌더링 최적화 및 시각적 반응성(Jank Prevention).
  • [SWEBOK v3: Software Design] — 뷰-데이터 동기화 아키텍처, 더블 버퍼링(Double Buffering) 디자인 패턴 기반 프레젠테이션 로직.

Secondary References

  • [React Core Architecture (Fiber)] — 재조정(Reconciliation) 엔진의 우선순위 스케줄러(Time Slicing) 및 중단 가능한 렌더링 틱(Tick).
  • [Immutability in JavaScript] — 가비지 컬렉터(GC) 압박과 불변 객체 생성 오버헤드 vs 참조 동등성(Reference Equality) 비교 성능의 트레이드오프.

Industry References

  • [React Documentation: Preserving and Resetting State] — UI 트리 위치에 따른 상태 유지(Preserve) 및 키(key)를 활용한 강제 리셋(Reset) 메커니즘.
  • [Vue/Svelte Internal Docs] — 가상 DOM 기반 런타임(React/Vue)과 가상 DOM 없는 컴파일 타임 반응성(Svelte) 렌더링 접근 방식 비교.

9. Final Checklist

Primary Checklist

  • React가 화면에 데이터를 렌더링할 때, 매번 브라우저의 실제 DOM 트리 전체를 삭제하고 다시 그리지 않고, 가상 DOM 비교(Diffing)를 거쳐 변경된 텍스트 노드만 수정하는(Patch) 최적화 과정을 설명할 수 있는가?
  • 배열 데이터를 map()으로 순회하여 UI 리스트를 렌더링할 때, 유니크 식별자(id) 대신 배열 인덱스(index)를 Key로 사용할 경우 배열 아이템 삭제/삽입 시 내부 상태(Input 입력값 등)가 꼬이는 물리적 원인을 아는가?

Secondary Checklist

  • setState 호출 시 불변성(Immutability)을 지키지 않고 객체 속성을 직접 수정(obj.value = 2)할 경우, V-DOM 엔진이 참조(메모리 주소) 동일성 얕은 비교(Shallow Compare)를 통과시켜 화면 렌더링을 누락하는 현상을 방어했는가?
  • 복잡하고 거대한 테이블이나 차트를 감싼 하위 컴포넌트가, 부모 컴포넌트의 단순한 색상 토글 버튼 클릭만으로도 연쇄적으로 불필요하게 렌더링되는 폭포(Waterfall) 현상을 React.memo로 차단(Bypass)했는가?

Industry Checklist

  • 컴포넌트 마운트(Mount) 시 부모의 타입(<div> ightarrow ightarrow <section>)이 변경되면, 하위의 100개 자식 트리가 완벽히 똑같더라도 디핑 휴리스틱에 의해 무조건 파괴(Unmount)되고 새로 생성되는 오버헤드를 아키텍처로 회피했는가?
  • 프로파일러(Profiler)를 통해 애플리케이션의 렌더링 성능을 측정할 때, "연산(Render/Reconciliation) 시간"과 실제 브라우저 "커밋(Commit/DOM Paint) 시간"을 구분하여 병목의 진짜 원인이 JS인지 브라우저 엔진인지 분리해냈는가?

Modern Web Framework Physics & Runtimes

1 / 4