[React]map 함수 적용 시 key props를 적용하는 이유

5448 단어 keykey

자료 출처 (공식문서): https://ko.reactjs.org/docs/lists-and-keys.html

JavaScript과는 조금 다른 JSX 문법의 큰 특징 중 하나는 "리스트의 각 항목에 고유한 key 값을 넣어야 한다는 점"이다. 각 list에 key값을 넣어주지 않으면 곧바로 화면에 경고창이 뜬다.

📛 key props 주지 않자 뜨는 경고창

내가 만든 코드를 예로 들자면,

배열로 이루어진 comments라는 state를 이용하여 댓글을 렌더링 하기 위해 comments를 Comment라는 자식 component로 mapping하였다. (Comment Component에서 렌더링할 댓글을 return한다)

그런데 key 값을 따로 주지 않았더니 노란색 줄이 그어졌다. 그리고 콘솔 창에는 바로 오류메세지가 떴다.

사실 화면 상에는 문제가 전혀 없다. 렌더링 자체는 잘 되지만 리액트 내에서 반드시 각 리스트는 각각의 '고유한 key값'을 갖고 있어야 한다고 권고한다.

다시 key값을 index의 값으로 넣어주었더니 노란색 밑줄도 없어지고, 오류메세지도 없어졌다.

🙋‍♀️ key 존재 이유

공식문서에 따르면, Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 도우며 key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 한다고 한다.
👉 즉 어떤 항목에 대한 변경사항을 알아차리기 위해 필요한 것이다.

React의 큰 특성중 하나가 변화가 나타난 그 구간만을 다시 렌더링한다는 것이다. (불필요하게 화면 전체를 다시 리렌더링 하지 않음)

배열 리스트 하나하나 고유한 key값을 부여함으로써 list상의 변화가 생겼을 때 그 부분만 리렌더링 할 수 있도록 하는 것이다.

🟡 id 값으로 index는 지양하라?

추가로 공식 문서에 따르면,
index값을 id로 주는 것은 최대한 지양하는 것이 좋다고 한다. (항목의 순서가 바뀔 경우)

왠만하면 배열의 state를 저장할 때 객체를 담은 배열의 형태로 저장하여 key값도 객체에 넣어주는 것이 좋겠다.

ex)
위의 코드에서 index를 key로 주었다면 아래에서는 직접 id를 생성하여 key값을 주었다.

const [comments, setComments] = useState([]);
let commentsCounter = 1;
const createComments = (comments) => (
[{comment,
  id: commentsCounter++}, ...comments]
)

{
  comments.map((comment) => (
    <Comment key={comment.id} />
  ));
}

⛔️ Key로 컴포넌트 추출 시 잘못된 사용법

키는 주변 배열의 context에서만 의미가 있다.
예를 들어 ListItem 컴포넌트를 추출한 경우 ListItem 안에 있는 <li> 엘리먼트가 아니라 배열의 <ListItem /> 엘리먼트가 key를 가져야 한다.

다음은 공식문서에 포함된 잘못된 Key 사용법이다.

function ListItem(props) {
  const value = props.value;
  return (
    <li key={value.toString()}>
      {value}
    </li>
  );
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

올바른 사용법은 아래와 같다.

function ListItem(props) {
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem key={number.toString()} value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

⭐️ 컴포넌트 추출할 경우 어디에 key값을 넣어줘야할 지 유의할 것!

🔖 추가) Key는 형제 사이에서만 고유한 값이어야 한다.

Key는 배열 안에서 형제 사이에서 고유해야 하고 전체 범위에서 고유할 필요는 없다. 두 개의 다른 배열을 만들 때 동일한 key를 사용할 수 있다!

🍯 마무리

key 값을 주는 이유가 React자체에서 쓸데없는 렌더링을 하지 않기 위해서라고 생각하니 정말 필수적으로 key값을 잘 주어야겠다는 생각이 든다. 까먹지말고 주자....! 리액트는 알면 알수록 편리하게 개발할 수 있게끔 잘 세팅된 환경 같다는 생각이 든다.

좋은 웹페이지 즐겨찾기