공부 및 일상기록

[React] map함수 사용시 key props를 사용해야 하는 이유 본문

개발/React

[React] map함수 사용시 key props를 사용해야 하는 이유

낚시하고싶어요 2023. 1. 12. 22:16

리액트를 다루면서 map 함수를 사용하면 가끔 Warning: Each child in a list should have a unique "key" prop. 와 같은 warning messge를 만나게 된다.

key prop warning

 

이는 map으로 반환한 엘리먼트에 key prop을 넘겨주지 않아서 발생하는 경고이다. 실제로 해당 경고가 있어도 정상적으로 작동하여 이를 무시하기 쉽지만 사실 이는 무시하지 못할 큰 역할을 하고 있다.

 

흔히 사용하는 index로 key를 입력하는 경우 어떤 문제가 있는지 알아보자

import { useRef, useState } from "react";

const Test = () => {
  const inputRef = useRef(null);
  const userList = [
    { id: 1, name: "민수" },
    { id: 2, name: "영수" },
    { id: 3, name: "창수" },
    { id: 4, name: "해수" },
  ];
  const [member, setMember] = useState(userList);
  const pushNewMember = () => {
    setMember([
      ...member,
      {
        id: member.length + 1,
        name: inputRef.current.value,
      },
    ]);
  };
  return (
    <div style={{ display: "flex", flexDirection: "column" }}>
      {member.map((user, index) => (
        <input
          key={index}
          type="text"
          placeholder={user.name}
          style={{ width: "100px" }}
        />
      ))}
      <input type="text" ref={inputRef} style={{ width: "100px" }} />
      <button onClick={pushNewMember} style={{ width: "100px" }}>
        추가
      </button>
    </div>
  );
};
export default Test;

해당 코드는 기존 길이가 4인 배열을 map을 이용하여 input태그를 만들었고, 하위 인풋에 이름을 추가하면 목록에 추가되도록 하는 코드이다. 

index로 하여도 문제가 없다..?

이렇게 순서가 보장되는 경우 큰 문제는 없다. 그렇다면 추가버튼을 누르면 위에 추가되도록 코드를 바꿔서 다시 한번 실행해본다.

const pushNewMember = () => {
    setMember([
      {
        id: member.length + 1,
        name: inputRef.current.value,
      },
      ...member,
    ]);
  };

이렇게 기존 4개 member 위에 추가되도록 해본다.

 

문제가..없나..?

문제가 없는것 처럼 보이지만 개발자 도구에서 보면 이상한 점이 느껴진다.

????? 모든 값이 리렌더링된다

개발자 도구에서 확인해 보면 모든 엘리먼트가 리렌더링 된다.

 

나는 단순히 하나만 앞에 추가하였는데 왜 모든것이 달라지는 걸까?

그 이유는 key도 함께 달라지기 때문이다.

리액트는 상태가 바뀌면 이전상태 트리와 이후상태의 트리를 비교한다. 이 때 key가 같다면 동일한 요소로 판별한다.

따라서 key가 모두 바뀌고 있으므로 이전 상태와 모두 달라진것으로 판단하여 모두 리렌더링 시키는 것이다.

만약 key가 없다면 전체를 리렌더링 시키게 된다.

또한 자세하게 보면 맨 위에 요소를 추가하였지만 기존의 key는 맨 아래에 추가되고 있으므로 input 태그가 생성되는것은 제일 하단이고, 나머지는 placeholder만 다시 그려준것을 볼 수 있다.

 

따라서 고유한 값을 key로 설정해야 추가되는 요소만 리렌더링 시켜줄 수 있게 된다.