
브라우저 렌더 엔진이 html 파일을 파싱해서 DOM Tree를 생성합니다.
CSS 파싱하여 CSSOM Tree를 생성합니다.
DOM Tree와 CSSOM Tree를 합쳐서 Render Tree를 생성합니다.
Render Tree의 각 노드를 화면에 어떻게 배치시킬 지 결정하기 위해서 Render Tree의 크기와 위치를 계산하여 다시 Render Tree에 반영하는 작업이 이루어집니다.
Painting 과정에서는 Layout 단계에서 계산했던 값을 이용하여 각 노드들을 실제 px 단위로 그려주는 역할을 합니다.
이러한 렌더링 과정들은 비용이 큰 작업입니다. Layout 단계를 다시 진행하는 것이 Reflow, Painting 단계를 다시 진행하는 것이 Repaint입니다.

다음 그림과 같은 코인 사이트에서는 실시간으로 바뀌는 코인의 가격을 끊임없이 업데이트 해줘야합니다.
가격이 변경될 때마다 Reflow 과정이 매번 일어나게 된다면 애플리케이션 성능이 안좋아집니다.
이것을 해결하기 위해 등장한 개념이 Virtual DOM입니다.
const domNode = {
tagName: "ul",
attributes: {
"class": "coaches"
},
children: [
{
tagName: 'li',
textContent: "준"
},
{
tagName: 'li',
textContent: "공원"
},
{
tagName: 'li',
textContent: "왼손"
},
{
tagName: 'li',
textContent: "크론"
},
]
}
Virtual DOM은 DOM 트리를 복제하여 메모리에 저장 시킨 자바스크립트 객체입니다.
DOM 정보는 가지고 있지만 DOM 조작 메서드는 없습니다.
Virtual DOM은 Real DOM을 경량화 했다고 표현하기도 합니다.
브라우저에서 DOM을 조작하면 렌더링과 리플로우 같은 비용이 발생하는 반면, Virtual DOM은 자바스크립트 객체로써 브라우저에서 직접 수정되지 않아서 위와 같은 비용이 발생하지 않습니다.
메모리상에서 변경 사항을 계산하고 필요한 경우에만 DOM Update를 하기때문에 굉장히 효율적이다.

데이터가 변경됨에 따라 DOM 업데이트를 매번 시키는 것이 아니라 Virtual DOM을 통해 변경된 것을 식별하여, DOM update를 한번 시키기 때문에 reflow도 한번 발생합니다.
무조건 효율적인 것은 아닙니다! DOM 업데이트가 많이 일어나는 경우만 효율적입니다!
정적 페이지 같은 경우 직접 DOM 업데이트 하는 것이 효율적일 수 있습니다.
Virtual DOM은 UI의 이상적인 또는 "가상"적인 표현을 메모리에 저장하고 ReactDOM과 같은 라이브러리에 의해 "실제" DOM과 동기화하는 프로그래밍 개념입니다. 이 과정을 재조정이라고 합니다.

function TestComponent(){
const [name, setName] = useState("크루");
const handleChangeName = () => {
setName("코치")
}
return (
<div>
<header></header>
<div>{name}</div>
<button onClick={handleChangeName}> 변경</button>
</div>
)
}
이 코드를 Babel을 이용해서 JS코드로 변환하게 되면 React.createElement 함수를 호출하게 됩니다.
const TestComponentElement = React.createElement("div", null, [...children]);
createElement 함수는 결과적으로 자바스크립트 객체를 반환하는데요.
const TestComponentElement = {
type: 'div',
props: {
children: [
{
type: 'header',
props: {
children: "우테코짱"
},
},
{
type: 'div',
props: {
children: "크루"
},
},
{
type: 'button',
props: {
children: "변경",
onClick: () => {
setName("코치")
}
},
},
]
}
}
이 자바스크립트 객체가 Virtual DOM입니다.
이 Virtual DOM을 어떻게 실제 DOM에 동기화할까요?
const container = document.getElementById("root");
ReactDOM.render(TestComponentElement, container)
ReactDOM의 render 메서드를 통해서 Virtual DOM을 실제 DOM에 동기화합니다.
React는 컴포넌트의 상태를 관찰하고 상태가 변경되면 해당 컴포넌트의 Virtual DOM을 업데이트합니다.
Virtual DOM을 업데이트 하기 전에 업데이트 전 Virtual DOM의 스냅샷을 찍어놓고, Virtual DOM을 업데이트한 다음에 두 개의 Virtual DOM을 비교하여 무엇이 다른지 비교하는 과정이 이루어집니다. 이때 Diffing Algorithm을 통해 해당 과정이 이루어집니다.
같은 타입의 두 React DOM(Virtual DOM) 엘리먼트를 비교할 때, React는 두 엘리먼트의 속성을 확인하여, 동일한 내역은 유지하고 변경된 속성들만 갱신합니다.
DOM 노드의 처리가 끝나면, React는 이어서 해당 노드의 자식을 재귀적으로 처리합니다.
이번 글에서는 Virtual DOM에 대해서 다뤘습니다. Virtual DOM은 실제 DOM의 가벼운 복사본이고 React는 이것을 활용하여 DOM 업데이트를 효율적으로 한다. 이정도의 지식만 가지고 있었는데요. 이번 영상을 통해 Virtual DOM이 왜 실제 DOM의 가벼운 복사본인지 어떻게 효율적으로 DOM을 업데이트 하는지 더 깊은 내용을 배웠습니다.