리액트 공식문서에서 틱택토 게임 만들기를 살펴보면 중간에 key에 대한 이야기가 나온다.
(틱택토 게임 만드는 방법은 생략! https://ko.react.dev/learn/tutorial-tic-tac-toe )
1. 리액트에서 리스트 항목에 대한 렌더링
리스트를 화면에 보여줄 때, React는 마치 메모장처럼 각 항목을 기억해둔다. 리스트가 바뀌면 (예: 새로운 항목 추가, 삭제, 순서 변경 등), React는 이전에 기억해둔 메모와 비교해서 실제로 무엇이 달라졌는지 찾아낸다.
장보기 목록을 적는다고 가정해보자. 리액트는 두개의 메모장을 가지고 이전 메모와 비교하여
- 장보기 목록에 '우유'를 추가했다면 → 새로운 항목이 추가된 것을 알아챈다.
- '계란'을 지웠다면 → 그 항목이 사라진 것을 파악한다
- 항목들의 순서를 바꿨다면 → 순서가 어떻게 바뀌었는지 확인한다
2. 리액트는 key를 이용하여 의도를 파악한다.
위의 메모장이 바뀐것을 인간은 쉽게 이해하지만, 컴퓨터 프로그램인 리액트가 어떻게 이해할 수 있을까?
바로 key를 이용하는 것이다. 무언가를 구별하여 부를때 이름을 붙이는듯 항목을 구별하기 위해 key를 붙인다.
<li key={user.id}>
{user.name}: {user.taskCount} tasks left
</li>
이 key 덕분에 React는 이전 리스트와 현재 리스트를 비교해서 어떤 항목이 유지, 추가, 제거되었는지 알아낼 수 있다.
- 새로운 key가 있는 항목: 이전에 없던 항목이 새로 생긴 경우이므로 그 항목에 해당하는 컴포넌트를 새로 만들어 추가.
- 없어진 key가 있는 항목: 이전에는 있었지만 현재 리스트에서는 없는 항목이므로 그 항목을 화면에서 제거.
- 같은 key가 있는 항목: 이전과 현재에 모두 있는 항목이므로 그대로 유지하고 위치만 이동해요.
key는 리액트가 각 컴포넌트를 구별할 수 있게 해 주는 속성이다. key 덕분에 컴포넌트가 다시 렌더링될 때에도 state를 유지할 수 있다. 만약 key가 바뀌면 리액트는 해당 컴포넌트를 새로 생성하기 때문에 기존 상태는 사라지고 초기 상태로 시작된다.
또한, key는 props처럼 보이지만, 일반 props와 달리 컴포넌트 내부에서 접근할 수 없는 특별한 속성이다. key는 리액트가 내부적으로 어떤 컴포넌트를 업데이트할지 결정하는 데만 사용된다. 컴포넌트는 부모가 설정한 key가 무엇인지 알 수 없고 단지 리액트가 이를 구분해서 필요한 업데이트를 해 줄 뿐이다.
Tip: 동적인 리스트를 만들 때는 항상 고유한 key를 지정하는 게 좋음! 만약 적절한 key가 없다면, 데이터를 재구성해서라도 구분할 수 있는 값을 만드는 게 안전하다.
3. 왜 배열 인덱스를 key로 쓰면 안 될까?
인덱스는 고유의 값이 아닌, 데이터에 항목이 추가, 제거 될 때마다 바뀔 수 있는 값이다. 리액트는 key를 보고 비교하는데, 인덱스를 사용하면 리스트에 변화가 생길 때마다 예상치 못한 방식으로 컴포넌트가 다시 렌더링될 수 있기 때문에 고유한 key를 만들어주는 게 중요하다.
인덱스 key를 사용했을 때 생길 수 있는 문제 상황
- 리스트 순서 변경: 리스트 항목의 순서가 바뀌면, 인덱스를 key로 사용한 경우 항목의 key 값이 그대로 있어서 리액트는 위치가 달라진 항목을 새로운 항목으로 인식하지 못한다. 그래서 항목의 내용이 맞지 않거나, 기존 상태가 꼬이는 문제가 생길 수 있다.
- 항목 추가 및 제거: 리스트 중간에 새로운 항목이 추가되거나 기존 항목이 삭제되면, 이후 인덱스들이 하나씩 밀리게 된다. 이 때문에 React는 남아 있는 항목들이 모두 새로운 항목으로 바뀌었다고 판단하고, 리스트를 처음부터 다시 렌더링하여 불필요하게 많은 렌더링이 일어나 성능이 저하될 수 있다.
'기술 > React.js' 카테고리의 다른 글
[문서] 리액트 공식문서 톱아보기: 컴포넌트 (0) | 2024.10.28 |
---|---|
[문서] 리액트 공식문서 톱아보기: 기본 문법(빠른 시작 가이드) (1) | 2024.10.27 |
react에서 vite로 env 설정해서 proxy 사용하기 (+CRA에서 proxy 설정) (0) | 2024.03.20 |
리액트에서 무한스크롤 구현하기(React-query, react-intersection-observer 사용) (1) | 2023.12.08 |
useState의 업데이트 방식에 따른 차이(함수형 업데이트) (0) | 2023.11.26 |