우선 리액트의 Virtual DOM(가상 돔)을 이해하기 위해서는 기존의 DOM Rendering 과정을 알아야 할 필요가 있는데요.
DOM(Document Object Model)은 간단히 얘기해서 '웹페이지에 보여질 콘텐츠 정보들의 계층적 구조' 인데, 보통의 웹브라우저에서는 다음과 같은 DOM의 렌더링 과정을 거쳐 해당 콘텐츠를 사용자에게 보여주는 CRP(Critical Render Path) 절차를 수행하게 됩니다.
- 사용자의 요청에 의해 브라우저가 해당 주소의 HTML 및 CSS 파일을 다운받은 후 각각의 브라우저의 렌더링 엔진(대표적으로 크롬은 V8)에 의해 파싱된 후 DOM Tree(HTML)와 CSSOM(CSS)를 를 생성합니다.
- 생성된 각각의 트리들을 결합하여 생성된 Render Tree를 기반으로 화면에 표시할 컨텐츠에 각 요소들의 레이아웃을 계산하고, 이 요소들이 화면에 나타날 좌표(위치) 및 크기 등을 결정합니다.
- 컨텐츠의 레이아웃 단계를 마친 후 색상 등 실체적인 모습을 그려내어 화면을 업데이트 합니다.
⭐ DOM의 기본적인 렌더링 과정은 다음과 같은 과정을 거치게 되며,
⭐ 이때 생성된 각각의 트리들이 결합되어 Render-Tree가 생성됩니다.
이때 사용자에 의해 정보가 입력되거나 특정 이벤트가 발생되면 각 브라우저의 엔진은 요소 제어를 위한 자바스크립트 파일을 다운 받은 후 DOM 객체에 접근하여 콘텐츠에 특정 요소나 속성을 선택한 후 해당 요소의 DOM Tree나 CSSOM의 특정 값을 업데이트 한 후 이를 기반으로 새로운 Render-Tree가 생성되어 다시 레이아웃(리플로우)을 계산하고 페인팅(리페인팅) 작업을 거쳐 화면에 출력시킵니다.
⭐ 문서 출처
문제는 이러한 DOM 렌더링의 과정이 일반적으로 동기적인 과정, 즉 웹 브라우저가 HTML을 파싱하는 도중 JavaScript 코드를 만나면(물론 async나 defer 키워드로 비동기 작업을 지원하는 방법으로 해당 문제를 해결) 해당 코드의 실행이 차단될 수도 있는데, 이럴 경우 해당 화면의 업데이트 처리가 지연될 수도 있고,
매번 해당 과정을 렌더링 해주다보니 발새 되는 비용이나 시간이 커질 수 밖에 없을 것입니다. 특히나 2010년대 부터 급진적으로 보급된 스마트폰 및 인터넷 사용량의 증가로 기존의 DOM이 가지고 있던 렌더링의 장점에도 한계점을 가질 수 밖에 없게 된 것이죠.
그래서 등장한 것이 바로 가상 돔(Virtual DOM)의 개념입니다. 간단하게만정리하면 "가상 돔에 실제로 사용자에게 보여질 요소를 업데이트 한 후 업데이트가 완료 되었을 때 실제 브라우저의 DOM에 반영하는 기술" 인데요.
이러한 가상 돔의 대표적인인 장점을 꼽자면, 기존의 사용자가 직접 DOM을 조작해야만 했던 기존의 ReRendering 방식에서 탈피하여 리액트가 자동적으로 특정 요소의 상태 변경을 감지하고 그 부분만 골라내어 업데이트 한 후에 즉각적으로 반영할 수 있다는 강점을 지니고 있습니다.
⭐ 자료 출처
리액트 v16 이전까지 가상 돔은 리액트 스택(React Stack) 알고리즘에 의해 생성 및 관리되었는데요. 문제는 이 엔진의 경우 단일 스레드에서 동작하는 자바스크립트 엔진에서 렌더링 작업을 수행하였기 때문에, 복잡한 UI에서는 블로킹 이슈 등으로 인한 렌더링 작업에 제약이 있었다는 것입니다.
그래서 이러한 문제를 해결하기 위해 리액트 v16 부터 등장한 것이 바로 리액트 파이버(React Fiber)인데요. 이전에 리액트 스택이 가지고 있던 동기적 렌더링 처리의 문제점을 해결하게 된 것이죠. 이러한 리액트 파이버는 재조정자(Reconciler)에 의해 관리되며
전체 작업을 작은 단위로 쪼갠 후 각각의 우선순위를 매기고, 우선 순위가 높은 작업을 우선적으로 처리하고 낮은 작업을 미루거나는 동안 이전에 했던 작업을 재활용 하기도 하고 사용하지 않는 작업에 대해서는 아예 폐기를 하는 방식으로 돔 트리의 업데이트를 처리합니다.
그리고 이러한 화면 UI의 작업을 위해 파이버에 의해 생성되는 리액트의 돔트리가 바로 'Current Tree' 와 'WorkingProgress Tree' 인 것이죠.
⭐ Current Tree는 파이버에 의해 생성되는 실질적인 화면 정보 트리이며, DFS 방식과 유사하게 Fiber Node를 구축하여 트리를 구성합니다.
'Current Tree'는 실제 사용자에게 보여지는 현재 컨텐츠 요소 정보들의 계층적 구조(트리)이고.
'WorkingProgress Tree'는 실체적으로 Current Tree에서 변경 되는 사항을 토대로 렌더링 작업이 이루어지는 트리라고 정리 할 수 있는데요.좀 더 풀어서 설명하자면, 사용자에게 보여지는 'Current Tree'를 구축할 때에는 각각의 컴포넌트 및 엘리먼트들을 깊이 우선 탐색(DFS)에 기반하여 탐색하고 FiberNode로 표현하여 해당 트리를 구축한 후
업데이트가 발생되면 파이버는 'Current Tree'를 복사한 'WorkingProgress Tree'에서 실질적으로 업데이트 되는 부분을 렌더링 한 뒤 'Current Tree`에 반영하는 방식이 바로 이 리액트 가상 돔의 원리인 것이죠.
⭐ 실질적인 업데이트는 복사된 Current Tree(WokrkingProgress Tree) 사본에서 렌더링 된 후 Current Tree에 반영됩니다.