Reconciliation[React]

SnowCat·2023년 3월 8일
0
post-thumbnail

동기

  • state나 prop이 갱신되면 리액트 컴포넌트는 새로운 리액트 엘리먼트 트리를 반환함
  • 이 때 리액트는 갱신된 트리에 맞게 효과적으로 UI를 갱신하고자 함
  • 하나의 트리를 다른 트리를 변환하기 위한 최소한의 연산수를 구하는 알고리즘이 O(n^3)이기 때문에 두가지 가정하에 O(n) 복잡도를 가지는 휴리스틱 알고리즘을 사용해 속도를 높임
      1. 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다
      1. 개발자가 key Prop을 통해 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 말아야 할지 표시해줄 수 있다.

비교 알고리즘

  • 두 개의 트리를 비교할 때 리액트는 두 엘리먼트의 루트 엘리먼트부터 비교하게 됨

루트 엘리먼트의 타입이 다른 경우

  • 두 루트 엘리먼트 타입이 다르면 (ex: div -> section) 리액트는 이전 트리를 버리고 새로운 트리를 구축함
    컴포넌트 마운트가 해제되면서 기존 DOM 노드들이 파괴되고 새로운 DOM 노드들이 삽입됨
  • 루트 엘리먼트 아래에 컴포넌트, state가 있었을 경우 모든 컴포넌트들도 언마운트되고, state도 사라지게 됨

루트 엘리먼트의 타입이 같은 경우

  • 타입이 같은 경우는 두 엘리먼트의 속성을 확인해 동일한 내역은 유지하고 변경된 속성들만 갱신함
  • DOM 노드의 처리가 끝나면 리액트는 이어서 해당 노드의 자식들을 재귀적으로 처리함
//before
<div className="" title="stuff" />

//after
<div className="isFancy" title="stuff" />
  • 이 경우 리액트는 className만을 갱신시킴

같은 타입의 컴포넌트 엘리먼트

  • 커포넌트가 갱신되면 인스턴스는 동일하게 유지 => 렌더링간 state는 유지됨
  • 새로운 엘리먼트 내용을 반영하기 위해 현재 컴포넌트의 prop을 갱신하고, 컴포넌트를 반환하며 비교 알고리즘이 재귀적으로 호출됨

자식에 대한 재귀적 처리

  • DOM 노드의 자식을 재귀적으로 처리할 때 두 리스트를 동시에 순회하며 차이점이 있을 때 변경을 생성함
<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>
  • 위의 예시의 경우 트리를 순화하면서 third List만을 트리에 추가하게 됨
<ul>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>
  • 하지만 위의 예시는 Connecticut만 트리에 추가하면 됨에도 불구하고, 모든 자식을 변경해야 하는 문제가 생김

Key

  • 리액트는 문제를 해결하기 위해 key를 사용
  • key를 비고해 기존 트리와 이후 트리의 자식이 일치하는지를 확인
// Connecticut만을 추가하면 된다는 사실을 알게 됨
<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>
  • 컴포넌트의 키는 데이터의 id, 해시, 배열의 인덱스 등을 사용하게 됨
    배열의 인덱스를 사용하는 경우 배열이 재배열되는 경우 항목의 순서가 바뀔 때 key가 바뀌기 때문에 state가 엉망이 되는 경우가 생길 수 있음에 주의

고려 사항

  • 알고리즘에서 다른 컴포넌트 타입을 갖는 트리들의 일치 여부는 확인하지 않음 => 비슷한 결과물을 출력할 경우 둘을 같은타입으로 만드는 것도 고려해볼 필요가 있음
  • key는 반드시 변하지 않고, 예상 가능하며, 유일해야 함 -> 지켜지지 않으면 필요없는 DOM 생성으로 성능이 저하되거나, state에서 문제가 생길 수 있음

출처:
https://ko.reactjs.org/docs/reconciliation.html
https://beta.reactjs.org/learn/preserving-and-resetting-state

profile
냐아아아아아아아아앙

0개의 댓글