리액트에서 배열을 렌더링할 때 key를 써야 하는 이유가 뭘까?

샤이니·2023년 4월 25일
0

잡학사전

목록 보기
12/18
post-custom-banner

배열을 렌더링할 때 key를 지정하지 않으면 다음과 같은 오류가 뜨는 것을 볼 수 있다.

Key를 지정하더라도 배열의 인덱스 같이 데이터를 구분할 수 없는 고유하지 않은 값으로 Key를 지정하면 렌더링이 잘못될 수 있다.

공식문서에 따르면..

Key는

  1. React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕고,
  2. 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야한다.

즉, 그 값이 변하지 않는 유일한 식별자의 역할을 가진다.

배열 렌더링에서 key의 역할

const items = [
  { id: 1, name: 'apple' },
  { id: 2, name: 'banana' },
  { id: 3, name: 'orange' },
];

function FruitList() {
  return (
    <ul>
      {items.map((item) => (
        <li>{item.name}</li>
      ))}
    </ul>
  );
}

key를 지정하지 않았을 때의 예시이다.

리액트는 각 아이템을 구분할 수 있는 고유의 값을 알지 못하기 때문에 배열이 업데이트 될 때 문제가 발생한다.

key가 없으면 리액트는 배열의 인덱스를 사용하여 업데이트를 수행한다. 그러나 배열의 인덱스는 항상 일정하지 않기 때문에 예측이 불가능하다.

예를 들어 배열에서 아이템을 삭제하면 인덱스가 변경됩니다. 그 결과, 리액트는 아이템이 삭제된 것으로 판단하지 않고, 단순히 인덱스가 변경된 것으로 판단하여 불필요한 렌더링을 발생시키게 된다..

즉, 나는 apple을 삭제하고자 했는데, banana가 삭제될 수도 있다는 것이다.

Key는 엘리먼트의 변화를 감지한다.

React에서는 컴포넌트가 상태(state) 변경, 이벤트 처리 등으로 인해 렌더링될 때, Virtual DOM을 통해 이전 렌더링 결과와 새로운 렌더링 결과를 비교하고 변경된 부분만 실제 DOM에 반영한다. 이때 배열도 마찬가지로 각 원소를 하나씩 비교하고 변경된 부분만 갱신한다.

리액트의 재조정(reconciliation) 과정

단계별로 보자면


1. virtualDOM에서 변화를 감지한다. 연두색 부분이 변경된 Node이다.


2. 변화가 일어난 virtualDOM과 realDOM을 비고해 새로운 DOM을 연산한다.


3. 비교 이후, realDOM은 virtualDOM과 동일하게 업데이트된다.

즉 realDOM은 모든 부분을 업데이트 하는 것이 아닌 변화가 감지된 부분만 업데이트한다.

따라서 Key를 사용한다면 React는 각 아이템의 고유한 식별자를 알 수 있기 때문에, 변경되 부분만 업데이트하고 나머지는 그대로 둘 수 있다.

만약 Key를 지정하지 않는다면, 어떤 요소가 변화된 것인지 명확하게 알 수 없기 때문에 모든 부분을 변경해야하는 것이다!

정리하자면?

요소마다 Key로 고유한 값을 지정해주면, 요소를 삭제, 추가하는 등 배열이 변경될 때, 정확히 어떤 요소가 변화한 것인지 알 수 있어서 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.

reference

https://junior-datalist.tistory.com/184
https://ko.legacy.reactjs.org/docs/reconciliation.html#recursing-on-children

post-custom-banner

0개의 댓글