문제 발생
udemy의 강의에 따라 진행을 하다보면 위와 같이 console
창에 key
경고 메세지가 출력되었다.
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `Expenses`.
See https://reactjs.org/link/warning-keys for more information.
새로운 값을 입력하여 동적으로 데이터를 추가할 수 있고 그 과정에서 아무런 문제가 없어보이는데 말이다.
이것은 React가 데이터의 목록을 렌더링하는 데 있어서 특별한 개념을 갖기 때문이다.
이 개념은 React가 발생할 수 있는 어떠한 성능 저하나 버그 없이 효과적으로 이러한 목록들을 업데이트하고 렌더링할 수 있도록 보장하기 위해 존재한다는 것이다.
브라우저[필자는 chorme]의 개발자 도구를 가보면 해당 페이지의 elements를 점검해 볼 수 있다.
사용자로부터 여러 정보를 받아 목록의 아이템으로 추가할 수 있는데 <div>
를 자세히 보면 깜빡이는 것을 볼 수 있다.
위와 같이 화면이 깜빡거렸다는 것은 브라우저에서 편집되었거나 추가되었다는 뜻이다.
새롭게 추가되는 아이템이 가장 위로 올라올 수 있게 만들어진 페이지이기는 하지만 기존에 있는 아이템들에게도 이렇게 깜빡이는 것을 볼 수 있다.
여기서 React는 새로운 아이템을 여기 <div>
목록에 있는 마지막 아이템으로 렌더링하고 모든 아이템을 업데이트해서 컨텐츠를 교체한다.
이렇게하면 배열의 항목 순서와 다시 일치되게 되는데 이는 그렇게 좋은 방식이 아니다.
이런 까닭은 React가 보기에는 모든 아이템들이 비슷하며 그저 목록이 길어진 것을 보았기 때문에 벌어진 일이다.
그래서 그대로 추가로 <div>
를 넣어 렌더링해서 마지막에 추가한 것이다.
그런 다음 모든 아이템들을 지나면서 배열의 컨텐츠와 일치하는지 확인하는 작업을 해준다.
이렇게 해서 최종 결과가 이뤄지기에 나름 적당해 보일 수는 있으나 성능적인 부분에서 해당 작업은 훌륭하지 못하다.
왜냐하면 모든 목록을 체크해서 업데이트해야하며, 이 과정에서 버그를 야기할 수도 있기 때문이다.
만약 해당 component가 stateful componenet라면 해당 state를 관리할 무언가가 존재할 것이다.
그리고 위 과정으로 새롭게 추가된 아이템은 특정 state를 가질 것이며 이전의 state를 완전히 덮어쓸 것이다.
그곳에 있었을 수도 있는 어떤 state의 변화는 사라질 것이다.
왜 이렇게 동작하는가?
사실 다른 방도가 없기 때문이다.
React에서는 간단히 배열의 길이를 체크하고 이미 렌드렁된 아이템의 수만 확인한다.
React가 느끼기에는 각각의 아이템들이 비슷해보일 것이다.
그렇기에 새로운 아이템이 어느 위치에 추가되야하는지 모르는 것이다.
그러한 이유에서 처음에 언급했던 경고 메세지가 출력되는 것인데, 새로운 아이템이 어디에 추가되어야하는지 React에게 알려줘야하기 때문이다.
이 문제를 해결하기 위해서는 아이템 목록이 출력되는 곳으로 가야한다.
다음 코드에서는 특별한 props를 추가해주었다.
return (
<div>
<Card className="expenses">
<ExpensesFilter
selected={filterYear}
onChangeFilter={filterChangeHandler}
/>
{props.items.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))}
</Card>
</div>
);
key
props는 해당 component에서만 사용하는 것이 아니며, 어떠한 component에서도 추가할 수 있다.
HTML 내장 요소든 사용자 지정 component든지간에.
이렇게 key
를 추가해준다면 React가 개별 아이템을 인식할 수 있게 도와줄 것이다.
여기서 사용되는 id는 달라야하며, 특정 컨텐츠를 갖는 모든 아이템들은 분명하게 고유한 id를 갖고 있어야한다.
실제 대부분의 시나리오에서는 고유값을 갖는데, 일반적으로 데이터베이스로부터 나온 데이터들은 각자 고유 식별자를 가지고 있다.
그 값은 숫자나 문자열도 상관하지 않는다.
그래서 위와 같이 수정해주면 처음의 key
경고 메세지는 더이상 나타나지 않는다.
그리고 개발자도구에서 새로운 아이템을 추가하면 기존의 아이템이 더이상 깜빡이지 않는 것을 볼 수 있다.
왜냐하면 React는 모든 아이템을 식별할 수 있게 되었기 때문이고 배열의 길이뿐만이 아니라 아이템이 위치해야할 곳까지 인식한다.
따라서 조금 더 효율적인 방법으로 업데이트를 할 수 있게 되었다.