가상 DOM과 key

  1. 가상 DOM의 역할:
    • React의 가상 DOM은 실제 DOM의 가벼운 복사본입니다.
    • 변경사항을 먼저 가상 DOM에 적용한 후, 실제 DOM과 비교하여 필요한 부분만 업데이트합니다.
  2. key의 목적:
    • key는 React가 어떤 항목이 변경, 추가 또는 제거되었는지 식별하는 데 도움을 줍니다.
    • key는 가상 DOM의 요소들을 구분하는 데 사용됩니다.
  3. index를 key로 사용할 때의 문제:
    • index를 key로 사용하는 것 자체가 가상 DOM의 재연산을 유발하지는 않습니다.
    • 문제는 리스트 항목의 순서가 변경되거나 항목이 추가/제거될 때 발생합니다.

index를 key로 사용할 때의 실제 문제

  1. 불필요한 리렌더링:
    • 리스트 항목의 순서가 변경될 때, index를 key로 사용하면 React는 많은 컴포넌트를 불필요하게 리렌더링할 수 있습니다.
    • 이는 성능 저하로 이어질 수 있습니다.
  2. 컴포넌트 상태 문제:
    • 각 리스트 항목이 자체 상태를 가지고 있을 때, index를 key로 사용하면 항목의 순서 변경 시 상태가 엉뚱한 컴포넌트와 연결될 수 있습니다.
  3. 재조정(Reconciliation) 문제:
    • React의 재조정 과정에서, index를 key로 사용하면 항목 추가/제거 시 React가 컴포넌트를 올바르게 식별하지 못할 수 있습니다.

예시

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo, index) => (
        <li key={index}>
          <input type="checkbox" />
          {todo.text}
        </li>
      ))}
    </ul>
  );
}

이 예시에서, 만약 리스트의 첫 번째 항목이 제거되면:

  • 모든 나머지 항목의 index가 변경됩니다.
  • React는 모든 항목이 변경되었다고 판단할 수 있습니다.
  • 결과적으로, 모든 <li> 요소를 다시 렌더링할 수 있습니다.
  • 체크박스의 상태같은 내부 상태도 잘못 유지될 수 있습니다.

해결책

  1. 고유한 ID 사용:
    • 가장 좋은 방법은 각 항목에 고유한 ID를 부여하는 것입니다.
    • 예:
      function TodoList({ todos }) 
        return (
          <ul>
            {todos.map(todo => (
              <li key={todo.id}>{todo.text}</li>
            ))}
          </ul>
        );
      }
       

2. 안정적인 고유 값 생성:

  • 데이터에 고유 ID가 없는 경우, 안정적인 고유 값을 생성할 수 있습니다.
  • 예를 들어, 항목의 내용과 인덱스를 조합하여 사용할 수 있습니다
    :
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo, index) => (
        <li key={`${todo.text}-${index}`}>{todo.text}</li>
      ))}
    </ul>
  );
}

3. 라이브러리 사용:

  • uuid나 nanoid 같은 라이브러리를 사용하여 고유 ID를 생성할 수 있습니다.
  • 예:

import { v4 as uuidv4 } from 'uuid';

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={uuidv4()}>{todo.text}</li>
      ))}
    </ul>
  )

주의사항

  • 인덱스를 key로 사용하는 것이 항상 잘못된 것은 아닙니다. 리스트가 정적이고 재정렬되지 않는 경우에는 인덱스를 사용해도 괜찮습니다.
  • 그러나 대부분의 경우, 고유한 ID나 안정적인 고유 값을 사용하는 것이 더 안전하고 효율적입니다.

+ Recent posts