List와 Key

박재현·2024년 2월 27일
0

Nomadcoder React Study 4기

목록 보기
18/49
post-thumbnail

새벽에 디스코드에서 이야기를 하다가 list와 map으로 여러개의 component를 렌더링할때 key를 왜 넣어줘야하는가?에 대한 이야기가 나왔었다.

어렴풋이만 알고있었고 왜 그런겁니다! 라고 명확하게 설명해드리지 못했어서 나도 한번 찾아봤다.

일단 콘솔창에 시뻘겋게 Warning : Each Child in a list should have a unique "key" prop. 이렇게 나오지만! 페이지는 정상적으로 작동한다 😱


일단, 데이터를 list에서 어떻게 렌더링하는지 코드를 통해서 보도록 하자.

const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

export default function List() {
  const listItems = people.map(person =>
    <li>{person}</li>
  );
  return <ul>{listItems}</ul>;
}

위 코드처럼 list에 있는 데이터들을 렌더링할 수 있다.
다만 key를 추가하지 않아서 당연히 warning은 발생한다 :)


Keeping list items in order with key

그러면 해당 warning을 없애려면 어떻게 해야하나? key를 넣어주기만 하면된다.
단, string 혹은 number 형태의 유니크한 값을(고유하게 식별할 수 있는) key로 넣어주면 된다.

<li key={person.id}>...</li>

Key

리액트의 장점은 필요한 부부만 렌더링한다는 것이다.
리스트를 생성할 때도 마찬가지로 배열 전체를 렌더링 하는게 아니라 업데이트된 부분만 계산해서 렌더링을 한다.

리스트가 [X, Y] 를 차례대로 렌더링한다고 가정해보자,
그 다음 Z라는 값이 추가 되어서 리스트가 [Z, X, Y] 순서로 변경되었다고 할때,
새로 들어온 Z라는 엘리먼트가 맨뒤가아닌 맨처음에 추가되면서 리스트의 순서가 변경되어 버린다.
(X, Y의 index가 1씩 밀리까)

사실상 X, Y의 값은 그대로이고 Z만 추가된건데, 순서가 뒤바뀌니 React는 이를 인식하지 못하고 리스트 전체를 다시 렌더링 해버리고, 이는 비효율적이라고 볼 수 있다.

key는 리액트가 어떤 항목을 변경, 추가 또는 삭제할지 식별 하는것을 돕는다.
key는 엘리먼트에 안정적인 고유성을 부여하기 위해서 배열 내부의 엘리먼트에 지정해야 한다.

key를 선택하는 가장 좋은 방법은 리스트의 다른 항목들 사이에서 해당 항목을 고유하게 식별할 수 있는 문자(또는 숫자)를 사용해야한다는 것! (대부분의 경우는 data의 id를 key로 사용한다)

우리가 컴퓨터를 할때, 바탕화면에 폴더를 여러개 만들어 두고 사용하지 않나?
근데 이때 폴더 이름을 다 숫자 1,2,3,4,...n 이런식으로 이름을 바꾸자고 가정해보자 (끔찍하네 ㅋㅋ)
이 상태에서 폴더가 추가되거나 삭제된다고 생각해보자.
그럼 숫자로된 폴더들이 어떤게 어떤 폴더였는지 내가 잘 기억할 수 있을까???
폴더 3개가 중간에 추가된다고 해보자, 그럼 내가 원하는 폴더가 어떤건지 명확하게 알 수 없을거 아닌가!
즉 key는 폴더의 이름과 같은 역할을 해준다고 볼 수 있다.

즉, 고유한 key를 통해서 엘리먼트가 이미 존재하는지, 새로 추가되었는지, 업데이트 되었는지 등등 판단하기 때문에 리스트 순서가 변경되어도 필요한 부분만 렌더링할 수 있게 된다.


Where to get your key

  • 데이터베이스에서 데이터를 갖고올때
    - 데이터가 데이터베이스로 부터 오는 경우라면, 데이터베이스의 keys또는ID를 유니크한 key로 사용할 수 있다.

  • 로컬에서 생성된 데이터
    - 데이터가 로컬에서 생성되고 유지되는 경우(ex: 메모앱) crypto.randomUUID() 또는 uuid 같은 페키지를 사용할 수 있다.

  • 렌더링한 항목에 대해 안정적인 고유한 id가 없다면 최후의 수단으로 항목의 index를 key로 사용할 수 있다.
    - 항목의 순서가 바뀔 수 있는경우 Key에 index를 사용하는것은 권장하지 않는다고함


Rules of keys

  • key는 변경되어서는 안된다! 렌더링될때 생성하지 말어라!
  • key는 컴포넌트로 전달하지 않기때문에 컴포넌트에서 key와 동일한 값이 필요하면 다른 이름의 prop을 만들어야 한다.
  • key는 형제 사이에서만 고유한 값이어야 한다.
    - key는 배열 안에서 형제 사이에서 고유해야하고, 전체 범위에서 고유할 필요는 없다!
    - 두개의 다른 배열을 만들때 동일한 key를 사용할 수 있다!
function Blog(props) {
  const sidebar = (
    <ul>
      {props.posts.map((post) =>
        <li key={post.id}>
          {post.title}
        </li>
      )}
    </ul>
  );
  const content = props.posts.map((post) =>
    <div key={post.id}>
      <h3>{post.title}</h3>
      <p>{post.content}</p>
    </div>
  );
  return (
    <div>
      {sidebar}
      <hr />
      {content}
    </div>
  );
}

const posts = [
  {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
  {id: 2, title: 'Installation', content: 'You can install React from npm.'}
];

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Blog posts={posts} />);

참고

profile
기술만 좋은 S급이 아니라, 태도가 좋은 A급이 되자

0개의 댓글

관련 채용 정보