본문 바로가기

Web.d

[React] map 함수에 key 값이 필요한 이유 (재조정; Reconciliation)

반응형

우리는 React app을 개발하면서 한 번쯤 map 함수를 사용하였을 것이다,

그 때마다 key 값을 넣어야 함도 알고 있다

그 이유에 대해서 한 번 알아보자

 


 

[Fig 1] 브라우저의 workflow

 

React에서 state나 props가 갱신되면

render() 함수는 새로운 Render Tree를 반환하며 reflow/repainting 과정을 거친다.

이를 리렌더링이라고 하는데, 그 중 Render Phase에서 재조정이 일어난다.

 

이에 대해 React는 최소한의 연산 수를 구하는 O(n) 복잡도의 휴리스틱 알고리즘을 구현하였다

다음 두 가정을 하며 말이다

 

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

 

Element의 타입이 다르다면,

React는 이전 트리를 버리고 완전히 새로운 트리를 구축한다.

 

그것이 아니라면,

React는 동일한 내역을 유지하고 변경된 속성들만 갱신한다 (className, style 등의 속성)

 

또한, 해당 인스턴스의 UNSAFE_componentWillReceiveProps(), UNSAFE_componentWillUpdate(), componentDidUpdate 를 호출한다

 

-

 

여기서 우리는 2번의 가정을 주목해보자

 


 

React는 DOM 노드의 자식들을 재귀적으로 처리할 때,

동시에 두 리스트를 순회하며 차이점에 대해 변경을 생성한다

 

예시 1)

 

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

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

 

위와 같은 경우에는, 쭉 살펴보며 마지막 <li>third</li> 를 트리에 추가한다

 

예시 2)

 

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

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

 

위와 같이 리스트의 맨 앞에 엘리먼트를 추가하게 되면,

공통된 종속 트리를 그대로 유지하는 대신 모든 자식을 변경하여

두 트리 변환이 비효율적으로 일어나게 된다

 

예시 3)

 

<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 를 가지고 있다면,

React는 key 를 통해 두 트리의 자식들이 일치하는지 확인하여

'2015' 와 '2016' key 를 가진 Element는 그저 이동만 하면 된다

 

즉, key 속성을 통해 비효율적인 트리 변환 문제를 해결할 수 있다

이는 오로지 형제 사이에서만 유일하면 되고, 전역에서 유일할 필요는 없다!

 

-

 

그렇다면 우리가 흔히 사용하는 map 함수의 index 값을 key 값으로 사용한다면?

--> 이는 또 다른 문제를 일으킨다

 

index 를 key 값으로 사용 중 배열이 재배열되면,

항목의 순서가 바뀌었을 때 key 또한 바뀔 것이기 때문에,

그 결과로 컴포넌트의 state가 엉망이 되거나 의도하지 않은 방식으로 바뀔 수 있다.

 

즉,

리액트 컴포넌트 내에서의 state를 보존하는 조건에는 최상위 요소의 태그, 요소의 순서를 확인하고, 달라진 경우에 재조정을 통해 state를 초기화 한다.

하지만 우선순위로써 key 값을 확인하고, 같으면 재조정을 막아 render pahse의 렌더링 과정을 막으며 최적화 할 수 있고 다르면 재조정을 야기한다.

따라서 같은 요소인 경우에, state 값을 새로 생성함을 막기 위해 key 값이 필요하고, 이는 불변하는 유일한 값을 사용함으로써 안전하게 관리한다는 것이다.

 

따라서, key 값을 index 값이 아닌 특정한 id 값으로 주는 것을 적극 권장한다

 


참고 자료

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

 

재조정 (Reconciliation) – React

A JavaScript library for building user interfaces

ko.reactjs.org

- https://pks2974.medium.com/react-%EC%9D%98-%EC%84%B1%EB%8A%A5%EC%9D%84-%EC%A1%B0%EA%B8%88-%EC%9D%B4%EB%9D%BC%EB%8F%84-%EC%98%AC%EB%A0%A4%EB%B3%B4%EC%9E%90-performance-optimize-f1a51b8c406c

 

React 의 성능을 조금 이라도 올려보자 (Performance Optimize)

React 의 성능을 올리기 위해 최적화 방법을 정리 해보고자 한다.

pks2974.medium.com

 

 

반응형