React에 key값이 필요한 이유

posinity·2022년 12월 7일
0

React

목록 보기
3/58

Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.

리액트는 최적화를 위해 key값을 가지고 렌더링을 한다. 컴포넌트 리스트를 렌더링 했을 때 어떤 요소에 변동이 있었는지 알아내기 위해 사용한다. key가 없는 경우엔 가상 DOM을 비교하는 과정에서 리스트를 순차적으로 비교하여 변화를 감지하는데, key가 있다면 이 값을 사용하여 어떤 변화가 있었는지 더욱 빠르게 알아낼 수 있다.

기존 트리를 가지고 다른 트리로 변환하기 위해 최소한의 연산을 하는 알고리즘 문제를 해결하기 위해 일반적으로 O(n^3)의 시간 복잡도를 가진다. 이대로 리액트에 적용한다면, 1000개의 엘리먼트를 그리기 위해 10억 번의 비교 연산을 해야하며, 이는 너무 비싼 연산이라고 리액트에서는 설명한다.
따라서, 리액트에는 두 가지 가정을 통한 휴리스틱 알고리즘을 적용하여 이 연산을 O(n)까지 줄일 수 있었다고 설명한다.

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

이 때, 사용되는 것이 key prop이다. 리액트에서는 key prop을 통해 컴포넌트를 새로 렌더하면서 엘리먼트 트리를 생성할 때, 더 빠르게 비교 연산을 수행하고 렌더할 수 있다.

리스트를 렌더할 때는 각 아이템이 고유한 id를 가질 수 있도록 하고, 해당 id를 key로 지정하는 것이 좋다.

key는 리스트의 순서를 비교하는 데 사용하는 값이며, 리스트를 렌더하고 있는 곳에서 key 를 넣어주어야 한다.
map 함수 내부에 있는 엘리먼트에 key를 넣어주는 것이 가장 일반적이다.

function ListItem(props) {
  // 이 곳에서 li에 key 값을 지정해도 별 효과는 없다.
  return <li key={props.id}>{props.value}</li>
}

function List(props) {
  const data = props.data;
  
  // 다음과 같이 ListItem 엘리먼트가 key를 가져야 한다.
  // 참고: key는 ListItem 엘리먼트의 prop으로 전달되지 않는다.
  return (
    <ul>
      {data.map((item) => <ListItem key={item.id} />}
    </ul>
  );
}

nanoid 나 uuid 같은 라이브러리를 사용하여 key를 지정할 때의 주의점

렌더할 때마다 nanoid나 uuid가 실행되지 않도록 주의하자. 렌더할 때마다 nanoid가 실행되는 불필요한 연산이 이루어질 뿐만 아니라, 기존 리스트와 비교하려는 시도가 무의미해지는 안티 패턴이다.

function List(props) {
  const data = props.data;
  return (
    <ul>
      {data.map((item) => <ListItem key={**nanoid(8)**} /> /* <- DON'T DO THAT */}
    </ul>
  );
}

인덱스를 Key로 지정하지 말자

map 함수의 index 값을 key로 설정하면, map 함수가 다시 실행되면서 index도 다시 생성된다. 이렇게 될 경우, 기존 리스트와 비교해서 최적화하려는 시도 자체가 무의미해진다. 즉, 안티 패턴이다.
key값을 지정하지 않았을 때 리액트에서는 기본적으로 index를 key로 사용한다. 따라서 key값을 반드시 지정해주도록 하자!

참고자료 : https://puterism.com/react-key/

profile
문제를 해결하고 가치를 제공합니다

0개의 댓글