Blog

리액트에서 key를 사용하는 이유


5 min read

서론#

React에서 리스트를 렌더링할 때 map을 쓰면
거의 항상 key 경고를 만나게 된다.

처음에는
"경고를 없애기 위한 값"처럼 보이기도 한다.

하지만 key는
단순한 옵션이 아니라
React가 리스트를 안정적으로 업데이트하기 위해 반드시 필요한 기준이다.

map을 사용할 때 왜 key가 필수인가#

React는 렌더링할 때
"이전 화면"과 "새 화면"을 비교해서
변경된 부분만 업데이트한다.

이 비교 과정에서
리스트의 각 항목이 어떤 항목이었던 건지를 구분할 기준이 필요하다.

그 기준이 key다.

즉 key는

"이 요소는 이전 렌더링의 어떤 요소와 같은 것인가?"

를 React에게 알려주는 값이다.

React의 렌더링 방식과 key의 역할#

리스트가 업데이트될 때는 보통 이런 변화가 생긴다.

  • 항목이 추가됨
  • 항목이 삭제됨
  • 항목의 순서가 바뀜
  • 항목 내용만 바뀜

React는 이 변화들을 처리하면서
가능하면 기존 DOM을 재사용하려고 한다.

key가 안정적이면

  • 같은 key는 같은 항목으로 인식하고
  • 필요한 부분만 업데이트한다

반대로 key가 없거나 불안정하면

  • 항목의 정체성이 흔들리고
  • 예상과 다른 재사용이 일어난다

결과적으로
UI가 “맞는 것처럼 보이지만”
상태나 입력값이 꼬이는 문제가 생길 수 있다.

index를 key로 사용하면 안 되는 이유#

index는 가장 쉬운 key다.

하지만 index는
리스트가 변할 때 항목의 정체성을 보장하지 못한다.

예를 들어

  • 0번, 1번, 2번 항목이 있던 리스트에서
  • 맨 앞에 항목이 하나 추가되면

기존 항목들은 그대로인데
index는 전부 1씩 밀린다.

React 입장에서는

  • "0번이던 요소가 1번이 됐네"
  • "그럼 1번 DOM을 재사용하면 되겠네"

같은 식의 판단을 하게 된다.

이 과정에서 문제가 생긴다.

  • 입력 컴포넌트의 값이 엉뚱한 항목으로 이동
  • 토글 상태가 다른 항목에 붙어버림
  • 애니메이션이 이상한 요소에 적용
  • 포커스가 튀거나 유지되지 않음

즉, index key 문제는
렌더링이 틀린 게 아니라
렌더링의 정체성이 어긋나는 문제다.

그럼 언제 index key가 괜찮은가#

완전히 금지 수준은 아니다.

index를 써도 크게 문제가 없는 경우는 보통 이 조건이다.

  • 리스트의 순서가 절대 바뀌지 않음
  • 항목의 추가/삭제가 없음
  • 항목 내부에 상태를 가진 입력/토글 같은 요소가 없음

즉, 정적인 목록일 때만 예외적으로 허용 가능하다.

하지만 실제 서비스에서는
이 조건을 만족하는 경우가 많지 않다.

해결 방법#

핵심은 단순하다.

key는 "항목의 고유 식별자"여야 한다.

그래서 해결 방법은 보통 아래 중 하나로 해결한다.

서버에서 내려오는 고유 id 사용 (권장)#

가장 이상적이다.

  • post.id
  • user.id
  • comment.id

같이 데이터가 가진 정체성을 그대로 쓰면 된다.


클라이언트에서 안정적인 id를 만들기 (차선)#

서버 id가 없거나, 임시 데이터라면
생성된 id가 렌더링마다 바뀌지 않게 관리해야 한다.

  • 데이터 생성 시점에 id를 부여하고 유지
  • 임시 목록이라면 uuid를 만들어 저장

포인트는 하나다.

렌더링마다 새로 생성한 값은 key로 쓰면 안 된다.
(예: Math.random(), 렌더링 중 uuid 생성)


불가피하면 “안정적인 조합 키” 사용 (최후)#

정말 id가 없다면
충돌 가능성이 낮은 조합으로 만든다.

  • type + createdAt
  • category + name

다만 이 방식은
데이터가 바뀌는 순간 key가 바뀔 수 있어서
최후의 선택에 가깝다.


정리#

key
React가 리스트를 그릴 수 있게 만드는 값이 아니다.

React가 리스트를 일관되게 업데이트할 수 있게 만드는 값이다.

그래서 key
"대충 넣는 값"이 아니라
항목의 정체성을 설명하는 중복되지 않는 값이어야 한다.

8