티스토리 뷰
React Key
리액트는 state, props가 변경되었을 때 리랜더링한다.
리랜더링은 render()함수를 다시 호출하는 것이고 이 때 새로운 React element tree를 반환한다.
이때 이전 상태로부터 변경된 요소를 확인하기 위해서 원래라면 O(n^3)의 복잡도를 갖는 연산을 수행한다.
그러나 리액트는 O(n)의 휴리스틱 알고리즘을 통해서 트리를 비교 연산한다.
- 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다.
- 개발자가
key
prop을 통해, 여러 렌더링 사이에서 어떤 자식 엘리먼트가 변경되지 않아야 할지 표시해 줄 수 있다.
비교 알고리즘
두 개의 트리를 비교할 때 두 엘리먼트의 Root부터 비교한다.
이 Root엘리먼트의 타입이 다른 경우 아예 새로운 트리를 구축하기 시작한다.
예를들어 다음과 같은 변환이 이루어질 때 를 뜻한다.
//이전
<div> 루트 -> a로 변경
<button/>
</div>
//변경
<a>
<button/>
</a>
트리를 버릴 때 이전 DOM노드들은 모두 파괴된다.
그래서 <button/>
이 이전과 동일하더라도 Root아래의 모든 컴포넌트가 삭제(언마운트)되고 그에 해당하는 state도 사라진다.
DOM element 타입이 같은 경우
같은 타입의 엘리먼트를 비교할 때 속성을 확인해 변경된 것들만 갱신한다.
DOM노드의 처리(갱신)가 끝나면 react는 해당 노드의 자식들을 재귀적으로 처리한다. -> 다음 자식노드들도 비교, 처리
자식에 대한 재귀적 처리
DOM노드의 자식들을 재귀적 처리할 때 React는 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성한다.
순회하는 것이 포인트.
다음 예제를 보자
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
위에서 아래로 변경되었을 때 React는 순회로 이 둘을 비교한다.
제일 마지막 자식이 추가되었으므로 기존 자식들은 그대로 두고 third
만 트리에 추가한다.
그러나 제일 앞에 추가되는 케이스는 매우 비효율적이다.
<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>
원래 첫째 자식인 Duke
가 Connect
로 변경되었으므로 React는 모든 자식을 변경해버린다.
=> 모두 없애고 재생성한다.
왜 다 없애버릴까? 그 이유는 key가 없기 때문이다.
Keys
위와 같은 문제를 해결하기 위해서 key
를 지원한다.
React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인한다.
<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>
아까와 같은 예제이지만 위 예제는 새로 생성되지 않는다. 2015, 2016키 요소가 "이동"만 될 뿐이다
이 이동은 정말 이동이다. 언마운트->마운트과정이 아니라 이동만된다.
그러나 이 key값을 인덱스로 주는 경우가 있는데 리스트 중간에 추가, 삭제가 일어나게 되면 문제가 발생할 수 있다.
예를들어 각 key가 인덱스인 0~100개의 요소가 리스트로 반환되고 있다고 해보자
중간 50번째 요소가 삭제되었다면 리액트는 이전트리와 key값을 비교하여 50번 key에 해당하는 요소만 없애고 그 뒤의 요소들을 "이동"시킬 것이다.
원래 51번요소가 50번째로 이동되는 것이다.
이에 관련한 예제는 공식문서에 나와있다 -
2. Key를 index로 했을 때, "이동"의 의미, 영상의 6:30초 구간을 확인해보자
여기서 말하는 재렌더링은 모든 컴포넌트의 render
를 호출하는 것이지 React가 언마운트시키고 다시 마운트하는 것은 아닙니다.
Key를 이용하면 언마운트-마운트 과정이 생략된다. 단순히 "이동"으로 끝난다.
그래서 리스트로 요소를 출력할 때 key를 사용해야하고, 의도치 않은 에러를 발생시키고 싶지 않다면 index를 key로 사용하지 말아야한다.
key를 넣지않으면 에러메세지를 콘솔로 알려주는 이유가 있다.
'프로그래밍 > React' 카테고리의 다른 글
React에서 Infinite scroll 구현하기 (IntersectionObserver) (0) | 2021.06.19 |
---|---|
Styled-Components With TS(theme, globalStyle) (0) | 2021.06.12 |
recoil 정리 (0) | 2021.05.25 |
Scroll Restoration (0) | 2021.04.30 |
SSR ,CSR (0) | 2021.04.20 |
- Total
- Today
- Yesterday