티스토리 뷰

Reconciliation이란 코드에 diff가 생겼을 때 DOM에 반영하는 로직이다. 공식 독스에서 크게 2가지를 중심으로 설명한다. 하나는 루트 엘리먼트의 타입이고, 하나는 key 어트리뷰트다.

Type diff of root element

  • 루트 엘리먼트의 type이 다른 경우
    • DOM element인지 React element인지를 불문하고 트리를 tear down하고 rebuild한다. (e.g. <img>와 <button>, <Comment />와 <Article />)
    • DOM이라면 해당 element를 제거하고 새로 삽입하고, React component라면 unmount했다가 새로 만들어서 mount한다.위 같은 경우 자식 컴포넌트는 동일하지만 root element의 type이 div와 span으로 다르므로, Counter 컴포넌트는 언마운트하고 새로 만들어서 마운트한다.
    • <div> <Counter /> </div> <span> <Counter /> </span>
  • 루트 엘리먼트의 type이 같은 경우
    • DOM element인데 type이 같은 경우, attribute를 확인하고 다른 attribute만 기존의 DOM에다가 업데이트한다.
    • React Component의 type이 같은데(=같은 컴포넌트인 경우) props, state에 변경사항이 있는 경우에는 re-rendering을 한다. (Unmount X)

Keys

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

이런 경우에는 마지막 li 컴포넌트만 삽입하면 된다.

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

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

하지만 이렇게 순서가 뒤바뀌는 경우에 리액트는 모든 li 컴포넌트를 바꿔버린다. 이는 비효율적이다. 새로 추가된 코네티컷 li만 추가할 수 없을까?

이런 문제를 해결하기 위해서 리액트는 key라는 attribute를 제공한다.

<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>

이렇게 key 어트리뷰트를 주면 리액트는 key가 2014인 li가 새로운 엘리먼트라고 인지하고, key가 2015와 2016인 것은 mutate하지 않고 그냥 위치를 옮기기만 한다.

그래서 이 key는 Id와 같은 역할을 하므로 고유해야 하고, 되도록 변하지 않는 것이어야 한다. 예를 들어 comments를 불러오는 API를 사용해서 map으로 컴포넌트를 나열할 때, key를 array index로 준다면, 다음에 렌더링될 때에는 key와 그 내용물이 맞지 않을 수 있다. 절대로 re order되지 않는 경우에는 괜찮을 수 있지만 느릴 것이다. (As a last resort, you can pass an item’s index in the array as a key. This can work well if the items are never reordered, but reorders will be slow.)

그래서 되도록 index를 key로 주는 것은 예상하지 못한 결과를 낼 수도 있으므로 피해야 한다.

Ref

https://reactjs.org/docs/reconciliation.html

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함