본문 바로가기
프로그래머로의 여정

React에서 map을 사용할 때 key의 의미와 중요성

by nunaaa 2025. 9. 4.

React에서 map을 사용할 때 key의 의미와 중요성

key의 기본 의미

React에서 key배열의 각 요소를 고유하게 식별하기 위한 특수 문자열 속성입니다. React가 Virtual DOM에서 어떤 항목이 변경, 추가 또는 제거되었는지 식별하는 데 도움을 줍니다.

key의 핵심 역할

1. 성능 최적화 (가장 중요한 역할)

// key가 없을 때: React는 모든 요소를 재렌더링
{items.map(item => (
  <ListItem item={item} /> // ❌ 성능 저하
))}

// key가 있을 때: 변경된 요소만 정확히 업데이트
{items.map(item => (
  <ListItem key={item.id} item={item} /> // ✅ 성능 최적화
))}

2. 상태 유지 보장

const todos = [
  { id: 1, text: "리액트 학습", completed: false },
  { id: 2, text: "과제 제출", completed: true }
];

function TodoList() {
  return (
    <ul>
      {todos.map(todo => (
        <TodoItem 
          key={todo.id} 
          todo={todo}
          // ✅ 체크박스 상태가 정확히 유지됨
        />
      ))}
    </ul>
  );
}

key가 필요한 이유: 구체적인 예시

❌ key가 없을 때 발생하는 문제

// 초기 배열
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

// 배열에서 Bob 제거 후
const updatedUsers = [
  { id: 1, name: 'Alice' },
  { id: 3, name: 'Charlie' }
];

// key 없이 렌더링하면 React가 혼동함
{users.map(user => <div>{user.name}</div>)}
/*
Alice
Bob    ❌ 삭제해야 할 요소
Charlie
*/

// React는 인덱스를 기준으로 판단하므로
// Bob이 사라지면 Charlie가 Bob의 위치로 이동한 것으로 인식

✅ key를 사용한 올바른 예

{users.map(user => (
  <div key={user.id}>{user.name}</div>
))}

/*
key="1" -> Alice
key="2" -> Bob    ✅ 정확히 삭제됨
key="3" -> Charlie
*/

key 선택 가이드라인

✅ 권장되는 key 값

// 1. 데이터베이스 ID (가장 이상적)
{posts.map(post => (
  <Post key={post.id} post={post} />
))}

// 2. 고유한 문자열 조합
{items.map(item => (
  <Item key={`${item.category}-${item.timestamp}`} item={item} />
))}

// 3. UUID 등 고유 식별자
{users.map(user => (
  <User key={user.uuid} user={user} />
))}

⚠️ 조건부로 사용 가능한 key

// 4. 배열 인덱스 (순서가 절대 변경되지 않을 때만)
{staticList.map((item, index) => (
  <StaticItem key={index} item={item} />
))}

❌ 절대 사용하지 말아야 할 key

// 5. Math.random() (매 렌더링마다 변경됨)
{items.map(item => (
  <Item key={Math.random()} /> // ❌ 매우 나쁨
))}

// 6. Date.now() (항상 변경됨)
{items.map(item => (
  <Item key={Date.now()} /> // ❌ 매우 나쁨
))}

// 7. 중복된 값
{items.map(item => (
  <Item key="same-key" /> // ❌ 안됨
))}

실제 React 내부 동작 방식

Virtual DOM 비교 알고리즘

// Before: [A, B, C] -> After: [A, C]
{items.map(item => <Item item={item} />)}

// key 없음: React는 인덱스로 비교
// 0: A -> A (재사용)
// 1: B -> C (B를 C로 변경) ❌ 비효율적
// 2: C -> (삭제)

// key 있음: React는 key로 비교
// key="a": A -> A (재사용)
// key="b": B -> (삭제) ✅ 효율적
// key="c": C -> C (재사용)

다양한 시나리오별 key 사용법

1. 중첩 배열에서의 key

const categories = [
  {
    id: 1,
    name: "전자제품",
    products: [
      { id: 101, name: "스마트폰" },
      { id: 102, name: "노트북" }
    ]
  },
  {
    id: 2,
    name: "의류",
    products: [
      { id: 201, name: "셔츠" },
      { id: 202, name: "바지" }
    ]
  }
];

function CategoryList() {
  return (
    <div>
      {categories.map(category => (
        <div key={category.id}>
          <h2>{category.name}</h2>
          {category.products.map(product => (
            <Product 
              key={product.id} // ✅ 각 수준마다 고유 key 필요
              product={product}
            />
          ))}
        </div>
      ))}
    </div>
  );
}

2. 필터링/정렬 시 key 중요성

const tasks = [
  { id: 1, text: "회의", priority: "high" },
  { id: 2, text: "이메일", priority: "low" },
  { id: 3, text: "보고서", priority: "high" }
];

function TaskList({ showHighPriorityOnly }) {
  const filteredTasks = showHighPriorityOnly
    ? tasks.filter(task => task.priority === "high")
    : tasks;

  return (
    <ul>
      {filteredTasks.map(task => (
        <TaskItem 
          key={task.id} // ✅ 필터링해도 상태 유지
          task={task}
        />
      ))}
    </ul>
  );
}

key 관련 디버깅 팁

일반적인 에러 메시지

Warning: Each child in a list should have a unique "key" prop.

해결 방법

// ❌ 문제: key 누락
{users.map(user => <User user={user} />)}

// ✅ 해결 1: 고유 ID 사용
{users.map(user => <User key={user.id} user={user} />)}

// ✅ 해결 2: 안정적인 key 생성
{users.map((user, index) => (
  <User key={`user-${user.name}-${index}`} user={user} />
))}

// ✅ 해결 3: 데이터 수정 시 key 유지
const updatedUsers = users.map(user => 
  user.id === targetId 
    ? { ...user, name: newName } // ✅ key 유지
    : user
);

결론

React에서 key는:

  • 성능 최적화를 위한 필수 요소
  • 상태 보존을 보장하는 장치
  • 변경 감지를 정확하게 하는 식별자
  • 고유성안정성이 가장 중요한 속성

항상 안정적이고 예측 가능한 고유 key를 사용해야 React 애플리케이션의 성능과 안정성을 보장할 수 있습니다.