als982001 2023. 3. 23. 15:07

1. Virtual DOM

  • Real DOM의 사본 (같은 것)
    • DOM(Document Object Model): 브라우저가 HTML 문서를 조작할 수 있게 트리 구조화한 객체 모델
    • 잦은 DOM이 변경, 업데이트 => 렌더링 엔진 리플로우 => 변화가 필요 없는 부분도 변경 => 성능 떨어뜨림
    • 바꾼 부분만 비교한 후, 그 부분만 렌더링하기 위해 Virtual DOM 등장.
  • Virtual DOM: JavaScript 객체로 이루어진 가상의 DOM 트리를 사용하여, 실제 DOM 조작을 최소화하고 성능을 최적화하는 기술
    • 변경이 필요한 부분만 실제 DOM에 반영, 업데이트 하기 때문에 전체를 다시 그리지 않아도 된다.

 

2 React Diffing Algorithm

2-1. 새로운 휴리스틱 알고리즘(Heuristic Algorithm)을 구현하기 위한 React의 두 가지 가정

  1. 각기 서로 다른 두 요소는 다른 트리를 구축할 것이다.
  2. 개발자가 제공하는 key 프로퍼티를 가지고, 여러 번 렌더링을 거쳐도 변경되지 말아야 하는 자식 요소가 무엇인지 알아낼 수 있을 것이다.

2-2. React DOM 트리를 탐색하는 방법

React의 DOM 트리 순회 방식

  • 트리의 레벨 순서대로 순회하는 방식 => BFS의 일종

 

2-2-1. 다른 타입의 DOM 엘리먼트인 경우

<section>
	<Some />
</section>

// 부모 태그가 section에서 h1으로 바뀜
<h1>
	<Some />
</h1>
  • 부모 태그가 달라질 경우 React는 이진 트리를 버리고 새로운 트리를 구축
  • 이로 인해 이전 DOM 트리 노드들은 전부 파괴됨
  • 위의 예시 속 <Some />은 완전히 해체된 후 다시 실행되기 때문에 <Some />이 갖고 있던 기존의 state 또한 파괴됨

 

2-2-2. 같은 타입의 DOM 엘리먼트인 경우

// 예시 1. className만 바뀌는 경우
<span className="title1">Title</span>
↓
<span className="title2">Title</span>

// 예시 2. 스타일만 바뀌는 경우 
<section style={{fontSize: "10px"}} title="stuff" />
↓
<section style={{fontSize: "100px"} title="stuff" />
  • 이 경우, React는 최대한 렌더링을 하지 않는 방향으로, 최소한의 변경사항만 업데이트함.
  • 이 때, 하나의 DOM 노드를 처리한 후, 뒤이어 해당 노드들 밑의 자식들을 순차적으로 동시에 순회하면서 차이가 발견될 때마다 변경하는데, 이를 재귀적으로 처리한다고 표현함

 

2-2-3. 자식 엘리먼트의 재귀적 처리

// 1. 자식 엘리먼트의 끝에 새로운 자식 엘리먼트를 추가
<ul>
	<li>1등</li>
	<li>2등</li>
</ul>
▼
<ul>
	<li>1등</li>
	<li>2등</li>
	<li>3등</li>
</ul>


// 2. 자식 엘리먼트를 처음에 추가
<ul>
	<li>1등</li>
	<li>2등</li>
</ul>
▼
<ul>
	<li>3등</li>
	<li>1등</li>
	<li>2등</li>
</ul>
  • 기존의 <ul>을 새로운 <ul>과 비교할 때 자식노드를 순차적으로 위에서 아래로 비교하면서 바뀐 점을 찾음
  • 그래서 React는 첫 번째 자식 노드들과 두 번째 자식 노드들이 일치하는 것을 확인한 후 세 번째 자식 노드를 추가함
  • 2번째 예시처럼 수정한다면 최소한으로 동작할 수 없음. 
  • 이를 해결하기 위해 필요한 것 => 키(key)

 

2-2-4. 키(key)

<ul>
	<li key="1등">1등</li>
	<li key="2등">2등</li>
</ul>
▼
<ul>
	<li key="3등">3등</li>
	<li key="1등">1등</li>
    <li key="2등">2등</li>
</ul>
  • 자식 노드들이 key를 가지고 있다면, 그 key를 이용하여 기존 트리의 자식과 새로운 트리의 자식이 일치하는지 아닌지 확인할 수 있음
  • 위의 예시에서, React는 그저 위치만 변경되었다는 것을 앎
  • 키는 전역적으로 유일할 필요없이, 형제 엘리먼트 사이에서만 유일하면 됨