[React] 재조정(Reconciliation)

이윤우·2023년 2월 9일
0

React

목록 보기
7/10
post-thumbnail

개요

리액트는 선언적 API를 제공하기 때문에 리액트의 사용자는 렌더링 작업을 함에 있어서 매번 무엇이 바뀌었는지를 걱정할 필요가 없습니다. 하지만 내부에서는 기존의 VDOM과 변경사항이 생긴 VDOM의 비교작업이 이루어집니다. 이 과정을 재조정(Reconcilitaion)이라고 합니다.

이 과정을 거치려면, 실제로 모든 DOM 트리를 순회하면서 탐색 및 변경하는 과정을 거쳐야 합니다. 하지만 이런 모든 과정을 거친다면 최첨단의 알고리즘을 이용해도 O(n^3)의 시간복잡도를 가진다고 합니다.

React는 대신, 두 가지 가정을 기반하여 O(n) 복잡도의 휴리스틱 알고리즘을 구현했습니다.

  1. 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다.
  2. 개발자가 key prop을 통해, 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해 줄 수 있다.

비교 알고리즘(Diffing Algorithm)

두 개의 트리를 비교할 때, React는 두 엘리먼트의 루트(root) 엘리먼트부터 비교합니다. 이후의 동작은 루트 엘리먼트의 타입에 따라 달라집니다.

  1. 엘리먼트의 타입이 다른 경우
    이전 트리를 완전히 버리고 새로운 트리를 구축합니다. 이전 트리와 연관된 모든 state는 사라집니다.

    <div>
        <Counter />
    </div>
    
    <span>
        <Counter />
    </span>
  2. 엘리먼트의 타입이 같은 경우
    변경된 속성들에 대해서만 업데이트됩니다. (Color 속성만 업데이트)

    <div style={{color: 'black', fontWeight: 'bold'}}>{count}</div>
    <div style={{color: 'red', fontWeight: 'bold'}}>{count}</div>

자식에 대한 재귀적 처리

DOM 노드의 자식들을 재귀적으로 처리할 때, React는 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성합니다.

자식의 끝에 엘리먼트를 추가하면 두 트리 사이의 변경은 잘 작동하지만 맨 앞에 추가하게 되면 성능이 좋지 않습니다. 아래의 경우엔 모든 자식을 변경하게 됩니다.

<ul>
	<li>Duke</li>
	<li>Villanova</li>
</ul>

<ul>
  	<li>Connecticut</li>
  	<li>Duke</li>
  	<li>Villanova</li>
</ul>

이를 해결하기 위해, React는 Key 속성을 지원합니다. 자식들이 key를 가지고 있다면, React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인하여 트리의 변환 작업이 효율적으로 수행되도록 합니다.

key props 선정할 때 유의점

  • 두 컴포넌트가 교체하는 상황에서는 그 둘을 같은 타입으로 만드는 것이 더 효율적이다.
  • key 값을 선정할 때는, 형제 사이에서만 유일하면 되고, 전역에서 유일한 value 일 필요는 없다.
  • 배열의 인덱스는 key로 사용하지 않는 것이 좋다. 항목들이 재배열되면, key 값이 변경될 수 있기 때문
  • key는 변하지 않고, 예상 가능하면서, 유일해야 한다. (Math.random() 같은 걸 key로 쓰면 안됨)

0개의 댓글