React.js:

[React] Virtual DOM에 대해

칠일오.

intro "이 사람 블로깅 갑자기 왜 이렇게 열심히 하지?"라는 생각이 든다면, 정답이다. 갑자기 열심히 하게 되었다..! 지금껏 여유도 없고 큰 필요성을 못 느끼기도 했고, 무엇보다 잘못된 정보나 사람들에게 보인다는 막연한 두려움 때문에 노션에 혼자 몰래 했었다. 그런데 혼자 보는 용으로 작성하다 보니 스스로 이해해서 작성하기보다는 그저 복사, 붙여넣기, 정리... 이런 식으로 작성하게 되다 보니 나에게 남는 게 크게 없다는 걸 느꼈다. 그래서 긴장감을 가지고 글을 진정성 있게 쓰기로 마음먹게 되어 앞으로 열심히 블로깅을 할 생각이다..! 최근 프로젝트를 하면서 리액트에 대해 스스로 부족한 점을 많이 느껴 리액트 시리즈로 블로깅을 시작해 보고자 한다. 서론이 너무 길었는데 바로 시작해 보겠다!

What is DOM?

DOM은 Document Object Model의 약어이다. 앞서 브라우저 렌더링에 대한 블로깅에서 다루었듯이, 웹 사이트에 접속하면 서버로부터 필요한 리소스를 받아오게 되는데, 이때 HTML은 브라우저 렌더링 엔진에 의해 DOM 트리로 파싱 하게 된다. DOM을 조작하면 web user interface에 반영되고, 일련의 과정을 거쳐 렌더링 된다.

+ 문법적 의미를 갖는 코드들을 객체로 변환하여 노드(node)들을 생성하게 되는데, HTML 요소는 중첩 관계를 가지기 때문에 이러한 부모-자식 관계가 반영되어 트리 자료구조로 만들어지는 것이다.

 

이렇듯 업데이트가 많다는 것은 DOM 조작이 잦다는 것이고, 이는 다시 리플로우, 리페인트 과정을 거쳐야 하다 보니 성능에 영향을 미치게 된다. 그래서 선배 개발자들은 "바뀐 부분만 비교해서 그 부분만 렌더링을 할 수는 없을까?"라는 생각을 하게 되었고, 그 생각이 실현되어 Virtual DOM이 세상에 나오게 되었다.

 

What is Virtual DOM?

리액트는 선언형(declarative)이다. 복잡한 과정을 추상화하여 결과에만 집중할 수 있게 한다. 이 말은 곧 리액트 내부에서 어떤 일이 일어나고 있는지 명확히 눈에 보이지 않는다는 말이기도 하다. 배열 고차 함수인 filter, map, reduce를 사용할 때를 생각해 보면 더 잘 와닿을 거라 생각한다. 이러한 리액트의 특징은 Virtual DOM 덕분에 가능한 것인데 리액트는 실제 DOM에 직접 업데이트하지 않고 실제 DOM 객체를 복사하여 변경된 요소만 업데이트한다. 복사된 DOM을 Virtual DOM(VDOM)이라 한다.

1. `Virtual DOM` 트리에서 각 요소는 노드로 표시된다.

2. 요소의 상태가 변경될 때마다 새로운 Virtual DOM 트리가 생성된다.

3. React의 diffing 알고리즘은 현재 Virtual DOM 트리를 이전 버전과 비교한다.

4. 마지막으로 VIrtual DOM은 diffing 알고리즘을 사용하여 실제 DOM을 업데이트한다.

 

⌗ Reconciliation (재조정)

리액트는 상태가 변경되면, 이전의 모습과 새로 반환된 요소를 비교하여 일치하지 않다면 실제 DOM을 업데이트하게 된다. 이러한 과정을 Reconciliation이라 한다. 리액트는 Diffing Algorithm (비교 알고리즘)을 통해 이를 수행한다.

The mechanism to diff one tree with another to determine which parts need to be changed and then update the original DOM with it is called Reconciliation.
React official

 

⌗ Diffing Algorithm (비교 알고리즘)

상태를 감지하고 업데이트해주기 위해서 최소한의 연산을 하는 알고리즘이 필요했고, 이를 해결하기 위해 나온 방법이 Diffing Algorithm이다.

1. Two elements of different types will produce different trees.
2. The developer can hint at which child elements may be stable across different renders with a key prop.
React official

그렇다면 리액트는 바뀐 요소만을 감지할 수 있을까라는 의문이 들었고, 그 답은 공식 문서에서 찾을 수 있었다.

// 이전 트리
<ul>
  <li>first</li>
  <li>second</li>
</ul>

// 새로운 트리
<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

만약 첫 요소에 변경이 있고, 아래 요소들이 같더라도 위치가 바뀌어 변경되었다고 감지한다면 전체 변경이 일어날 것이고 이는 성능에도 영향을 준다. 하지만 리액트는 자식들에게 Key 값을 할당하여 기존 트리와 새로운 트리의 요소들이 일치하는지 확인하여 변경된 key만 업데이트한다.

가상 돔의 개념은 실제로 렌더링 되지 않고 연산이 끝나면 실제 돔에 반영되기 때문에 연산 비용이 적게 든다는 이점이 있다. 또한 속도 면에서도 훨씬 빠르다. 그렇기에 SPA에서도 빛을 발휘하는 이유라고 생각한다.

 

2023.04.10. 0:15


📜 출처