far

[React] Key에 대하여 (Map의 key props) 본문

React/기록

[React] Key에 대하여 (Map의 key props)

Eater 2023. 3. 15. 16:31

React의 Map을 사용하다가 고유값이 없어서 index를 넣은 경험이 있는데, index를 사용해도 될 때는 언제지? 싶어서 관련 내용을 좀 찾아봤다. 그런데 글들을 읽어보니 내가 생각보다 key의 역할에 대해 잘 알고있던게 아니구나 싶어 이 참에 Key props에 대해 정리를 하려고 한다.

 

Virtual DOM이 DOM에 새 엘리먼트를 추가하는 방식

<ul>
  <li>Pen</li>
  <li>Cup</li>
</ul>

변경전

<ul>
  <li>Pen</li>
  <li>Cup</li>
  <li>Note</li>
</ul>

변경후

 

리액트의 Virtual DOM(가상돔)은 위에서부터 Virtual DOM의 <li>Pen</li>과 DOM의 <li>Pen</li>를 비교 해나간다. 그리고 변경 사항이 없다면 <li>Cup</li>로 넘어가 Virtual DOM과 DOM이 같은지 비교한다. 그러다 DOM에 없는 <li>Note</li>를 만났을 때 DOM에 <li>Note</li>를 추가해준다.

 

<ul>
  <li>Pen</li>
  <li>Cup</li>
</ul>
<ul>
  <li>Note</li>
  <li>Pen</li>
  <li>Cup</li>
</ul>

하지만 위처럼 DOM에 새로 추가 될 엘리먼트가 최상단에 삽입 될 경우 한칸씩 밀리는게 아니라, 모든 데이터가 바뀌게 되므로 불필요한 리렌더링이 일어난다.

 

Key가 필요한 이유

위의 문제를 해결하기 위해 도입 된 것이 Key이다.

key는 리액트가 어떤 항목을 변경하거나 추가 또는 삭제를 할 때 식별하는 걸 도와준다.

<ul>
  <li key="A">Pen</li>
  <li key="B">Cup</li>
</ul>
<ul>
  <li key="C">Note</li>
  <li key="A">Pen</li>
  <li key="B">Cup</li>
</ul>

위의 코드처럼 key를 추가해주면 C라는 키를 가진 엘리먼트가 추가되었고 A와 B라는 키를 가진 엘리먼트는 변경되지 않았기에 이동만 하면 된다고 인식한다.

 

Map사용시의 key

<div className="post">
  {mainPosts.map((post) => {
      return (
        <PostCard key={post.articleId} post={post} />
      )
  })}
</div>

일반적으로 key에 넣는 고유값은 데이터에서 받은 id(데이터베이스의 private key)를 사용한다. 그 외 UUID같은 중복되지 않는 문자열도 사용 가능하다.

 

const item = item.map((v, i) =>
  <li key={i}>
    {v.content}
  </li>
);

 

key에 index를 사용하면 정렬 순서가 바뀔 경우 index도 전부 변경되기에 어쩔 수 없는 경우를 제외하면 사용하지 않는 편이 좋다. (참고로 React는 key를 지정하지 않을 경우 index를 키로 사용한다.) 반대로 말하면 정렬 순서가 바뀌지 않으면 index를 key로 사용해도 된다는 말이기도 하다. 예를 들어 페이지의 변경이 없는 정적 페이지라던가 말이다.

 

 

Comments