티스토리 뷰

프로그래밍/React

React에서의 Key의 역할

수박수박좋다 2021. 4. 20. 19:09
반응형

React Key

리액트는 state, props가 변경되었을 때 리랜더링한다.

리랜더링은 render()함수를 다시 호출하는 것이고 이 때 새로운 React element tree를 반환한다.

이때 이전 상태로부터 변경된 요소를 확인하기 위해서 원래라면 O(n^3)의 복잡도를 갖는 연산을 수행한다.

그러나 리액트는 O(n)의 휴리스틱 알고리즘을 통해서 트리를 비교 연산한다.

  1. 서로 다른 타입의 두 엘리먼트는 서로 다른 트리를 만들어낸다.
  2. 개발자가 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>

원래 첫째 자식인 DukeConnect로 변경되었으므로 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번째로 이동되는 것이다.

이에 관련한 예제는 공식문서에 나와있다 - 컴포넌트의 Key를 Index로 바꿔서 확인해보자.

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
농담곰의 고군분투 개발기