React에서 index를 key로 쓰면 안 되는 이유
date
Jan 26, 2026
slug
react-index-as-key
author
status
Public
tags
Study
summary
React는 리스트를 렌더링할 때 key를 기준으로 이전 요소와 새로운 요소를 매칭한다. index는 항목의 위치 정보이기 때문에 중간 삽입이나 삭제가 발생하면 값이 바뀌고, 이로 인해 React가 서로 다른 데이터를 같은 컴포넌트로 인식해 state나 DOM을 잘못 재사용할 수 있다. 따라서 key로는 index 대신 변경되지 않는 고유한 id를 사용하는 것이 안전하다.
type
Post
thumbnail
category
💻 Frontend
updatedAt
Feb 11, 2026 08:25 PM
면접을 보면서 받은 질문 중 하나가 있었습니다.
리스트 렌더링할 때 key로 index를 쓰면 안 되는 이유가 뭔가요?
해당 질문에 대해 정확하게 알지 못해서 “수정이 안 되고, 문제가 생겨서입니다.”라고 답변할 수 밖에 없었습니다.
틀린 말은 아니지만, 정확한 이유는 아니라고 생각하였고 이 글에서 “왜 안 되는지”를 React의 동작 방식 기준으로 정리해보면서 공부해보고자 합니다.
key는 단순한 옵션이 아니다
React에서
key는 단순히 경고를 없애기 위한 값이 아니고 리스트 아이템의 정체성을 알려주는 힌트입니다.React는 리렌더링할 때 이런 작업을 합니다.
- 이전 렌더 결과
- 새로운 렌더 결과
이 둘을 비교해서 “어떤 요소가 그대로고, 어떤 요소가 바뀌었는지”를 판단하는데 이때 사용하는 기준이 바로
key입니다.React는 key로 “같은 컴포넌트인지” 판단한다
리스트를 렌더링할 때 React는 이렇게 생각합니다.
“이 key를 가진 요소는 이전에도 있었네? 그럼 같은 컴포넌트로 보고 재사용하자.”
즉, key는 순서가 아니라 정체성을 나타내야 합니다.
index가 문제인 이유
index는 아이템의 위치일 뿐, 데이터의 정체성이 아닙니다.{items.map((item, index) => ( <Item key={index} value={item} /> ))}
이 코드는 처음엔 멀쩡해 보이지만 리스트에 변화가 생기면 문제가 시작된다.
- 중간에 아이템 추가
- 아이템 삭제
- 정렬 변경
- 필터링
- 드래그 앤 드롭
이런 순간마다 index는 바뀌기 때문입니다.
가장 흔한 버그: input 값이 다른 줄로 이동
{todos.map((todo, index) => ( <TodoRow key={index} todo={todo} /> ))}
각
TodoRow 안에 input이 있다고 가정합니다.- 첫 번째 항목을 삭제한다
- 원래 두 번째였던 항목이 첫 번째 위치로 올라온다
- 하지만 key는 여전히
0
React 입장에서는
“key가 0이네? 이전에 있던 0번 컴포넌트 그대로 쓰면 되겠다.”
그렇게 되면 결과는
- input에 입력하던 값이 다른 항목에 붙어 보임
- 포커스가 튐
- 체크박스 상태가 섞임
데이터는 바뀌었는데, 컴포넌트는 그대로 재사용되는 것 입니다.
또 다른 문제: 컴포넌트 state가 섞인다
아이템마다 로컬 state가 있는 경우도 문제가 발생합니다.
예를 들어:
- 열림/닫힘 상태
- 선택 여부
- 애니메이션 상태
index를 key로 쓰면 리스트 순서가 바뀌는 순간 state가 다른 아이템으로 이동할 수 있습니다.
핵심 정리: index는 “위치”다
정리하면
- key는 아이템의 정체성
- index는 현재 위치
위치는 바뀔 수 있지만, 정체성은 바뀌면 안 되기에 index는 key로 부적절합니다.
그럼 index는 항상 안될까?
항상 안 되는 건 아니고 아래 조건을 모두 만족한다면 index를 써도 큰 문제가 없습니다.
- 리스트가 정적이다
- 순서가 절대 바뀌지 않는다
- 각 아이템이 state를 거의 가지지 않는다
- input, 포커스, 애니메이션 같은 요소가 없다
예를 들면:
- 고정된 순위표
- 단순 텍스트 목록
- 서버에서 내려온 “읽기 전용” 리스트
하지만 이 조건을 완전히 만족하는 경우가 거의 없습니다.
올바른 방법: 안정적인 고유 key 사용
가장 좋은 방법은 데이터가 가진 고유 ID를 key로 사용하는 것입니다.
{todos.map((todo) => ( <TodoRow key={todo.id} todo={todo} /> ))}
만약 서버에서 id가 없다면?
- 데이터를 생성할 때 uuid / nanoid 등을 붙여서 데이터 자체에 key를 저장하는 게 좋습니다.
⚠️
Math.random()을 key로 쓰는 건 렌더링마다 key가 바뀌어서 모든 컴포넌트가 새로 마운트되므로 더욱 위험하다.면접 답변
면접으로 돌아간다면 이렇게 말할 것 같다.
React에서 key는 리스트 항목의 정체성을 구분하기 위한 값인데, index는 위치 정보라서 삽입이나 삭제, 정렬이 발생하면 값이 바뀝니다. 그 결과 React가 서로 다른 데이터를 같은 컴포넌트로 잘못 매칭해 state나 input 값, 포커스가 다른 항목으로 이동하는 버그가 생길 수 있습니다. 그래서 key로는 index 대신 변경되지 않는 고유한 id를 사용하는 것이 안전합니다.
마무리
“index를 key로 쓰면 안 된다”는 말은 규칙이 아니라 결과를 피하기 위한 가이드에 가깝습니다. React가 어떻게 비교하고, 왜 그런 버그가 생기는지를 이해하면 언제 써도 되는지, 언제 피해야 하는지도 자연스럽게 판단할 수 있다고 생각합니다. 이 글이 면접을 준비하거나, 리스트 버그를 겪고 있는 누군가에게 도움이 되었으면 좋겠습니다.