[React] List와 Key의 중요성

혜빈·2024년 7월 25일

REACT 보충개념

목록 보기
44/48
  • React에서 List 형태로 여러 element들을 반환할때는 각각의 element마다 고유한 key값을 넣어줘야 함
const list = [
  { id: '1', value: '수영하기' },
  { id: '1', value: '요가하기' },
  { id: '1', value: '헬스하기' },
];

<ul>
  {list.map((item) => {
  	return <li key={item.id}>{item.value}</li>
  })}  
</ul>

key값

  • List 내부의 각각 element의 key값은 안정적이고 고유한 값이어야 함

실제 코드 구현

import { useState } from "react";

function List2() {
  const [inputValue, setInputValue] = useState("");
  const [list, setList] = useState(["수영하기", "요가하기"]);

  const addTodoList = () => {
    setList((prevList) => {
      return [inputValue, ...prevList];
    });
    setInputValue("");
  };

  return (
    <>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <button onClick={addTodoList}>추가</button>
      <ul>
        {list.map((item) => {
          return <li>{item}</li>;
        })}
      </ul>
    </>
  );
}

export default List2;

  • 위 처럼 코드를 작성하면 key를 추가해달라고 경고가 발생함

  • key를 추가하지 않은 상태에서 list에 하나의 항목을 추가하면
    모든 li element들이 DOM 상에서 업데이트가 됨

  • 각 list 항목에 key를 추가해주지 않았기 때문에
    React는 어떤 항목이 업데이트 되었는지 알지 못해서 모든 항목들을 전부 업데이트 시켜준 것임

  • 만약 규모가 큰 작업이라면 새로운 것을 추가할때마다 모든 항목들이 DOM 상에서 업데이트 되기 때문에 굉장히 비효율적임 -> 각 항목에 key를 넣어주자!

  • 이렇게 추가해주면 새롭게 추가된 항목만 DOM 상에서 업데이트 됨
  • React가 각 key를 통해 어떤 항목이 변경되었고, 변경되지 않았는지 알 수 있기 때문임

주의할점

  1. 안정적이지 않은 key값을 사용한 사례
  • map이라는 함수는 두 번째 인자로 index를 주기 때문에 key값으로 편하게 index값을 넣어주는 경우가 많음
    - 하지만 index를 key값으로 넣어주는 것은 좋지 않음
  • 위에서 본 상황처럼 모든 항목들이 DOM 상에서 업데이트가 됨
  • 새로운 항목이 들어올때마다 index들이 변경되기 때문에 React는 key값이 안정적이지 않다고 인지하고 모든 항목들을 전부 교체해줌
    - 변경되지 않는 정적인 list는 key를 index로 넣어줘도 되지만,
    변경되는 동적인 list는 key를 index로 넣어주지 않는것이 좋음

key값을 index로 준 경우


  return (
    <>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <button onClick={addTodoList}>추가</button>
      <ul>
        {list.map((item, index) => {
          return (
            <div key={index}>
              <li>{item}</li>
              <input />
            </div>
          );
        })}
      </ul>
    </>
  );
}

key값을 item으로 준 경우


  return (
    <>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <button onClick={addTodoList}>추가</button>
      <ul>
        {list.map((item, index) => {
          return (
            <div key={item}>
              <li>{item}</li>
              <input />
            </div>
          );
        })}
      </ul>
    </>
  );
}

- 결론 : 동적인 list를 만들 때는 index를 key값으로 사용하지 않기!


  1. 중복된 key를 사용한 사례

function List2() {
  const [inputValue, setInputValue] = useState("");
  const [list, setList] = useState(["수영하기", "요가하기"]);

  const addTodoList = () => {
    setList((prevList) => {
      return [inputValue, ...prevList];
    });
    setInputValue("");
  };

  return (
    <>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <button onClick={addTodoList}>추가</button>
      <ul>
        {list.map((item) => {
          return <li key={item}>{item}</li>;
        })}
      </ul>
    </>
  );
}

  • 이렇게 하면 '수영하기'가 두 번 존재하기 때문에 key값이 중복됨
  • 중복된 key를 가지고 있을 때는 자녀가 복제될 수도 있고 업데이트가 이상하게 될 수도 있음

해결방법

function List2() {
  const [inputValue, setInputValue] = useState("");
  const [list, setList] = useState([
    {
      id: "1",
      value: "수영하기",
    },
    {
      id: "2",
      value: "요가하기",
    },
  ]);

  const addTodoList = () => {
    setList((prevList) => {
      return [
        {
          id: list.length + 1 + "",
          value: inputValue,
        },
        ...prevList,
      ];
    });
    setInputValue("");
  };

  return (
    <>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <button onClick={addTodoList}>추가</button>
      <ul>
        {list.map((item) => {
          return <li key={item.id}>{item.value}</li>;
        })}
      </ul>
    </>
  );
}
  • 이렇게 변경해주면 됨
profile
최강 개발자를 꿈꾸는 병아리

0개의 댓글