TIL 19_React에서 key의 역할 🔑

dudgus5766·2021년 8월 21일
1

React

목록 보기
1/8
post-thumbnail

React에서 key가 필요한 이유

리액트를 만지다 보니 statekey값을 사용할 때 index 값을 사용하면 위험하다!⚠️ 라는 것은 들어본 적이 있다. 이유는 모른 채 그냥 Date.now() 메소드 만 썼는데..왜 일까?

리액트를 사용하다보면, state로 배열을 관리해야 할 경우가 상당히 많다. 예를 들어 서버로부터 게시글 목록을 받아온다면, 아래와 같은 배열 리스트를 받아서 state로 저장할 수도 있다.

key?🔑

배열의 각 요소마다 고유한 key값을 지정해 주는 속성인데 만약 key값을 생략한다면 어떻게 될까?
아마 이상없이 랜더링은 되겠지만, React는 아래와 같은 경고를 띄운다.

Each child in an array should have a unique “key” prop.

그럼 key값은 언제 필요한 것일까?

요소의 변화를 알아차리기 위해 필요하다.

리액트 공식문서를 보면, key는 어떤 아이템이 변화되거나, 추가, 삭제되었는지를 알아차리기 위해 필요하다고 말한다.

리액트는 state에서 변경사항이 있는 부분만 캐치해서 리랜더링 해준다. 리액트 유저라면 알고겠지만, 굳이 변경이 없는 데이터까지 Dom을 조작해서 불필요한 자원을 낭비하지 않겠다는 것이다.

배열에 고유한 key값을 넘겨주었을 시에는 state의 배열에 어떤 요소를 추가해도 react는 배열 전체를 리랜더링 하지 않는다. 배열에 추가된 요소 한가지만 다시 리랜더링한다.




단순히 key값으로 index를 쓰는 것이 왜 좋지 않은가

간단하게 한줄로 요약해보자면 원하지 않는 데이터가 보여질 수 있기 때문이다.

배열의 첫 번째 위치에 새로운 값을 넣었다고 쳐보자.

{id:4, title:"ah!", content:"yeah!"}

이 값을 배열의 맨 앞에 넣어다고 생각하면 될 것 같다. 그리고 나서 map을 돌릴 때, key값을 단순히 index로 주게 된다면 post.id는 무시된채 아래와 같은 상황이 될 것이다.

key: 0,  {id:4, title: 'ah!', content:'yeah!'},
key: 1,  {id:0, title: 'hello!', content:'word'},
key: 2,  {id:1, title: 'myname!', content:'is!'},

결국 리액트가 판단했을 때, 배열 전체를 리랜더링 하면서 기존의 정렬이 전부 다 바뀌게 된다. 기존에는 key:0인 것이 {id:0, title: ‘hello!’, content:’word’} 였는데, 새로 들어온 요소가 key:0이 되고, 기존의 key:0key:1이 되었으니 결과적으로 key 값을 index로 사용한다면 배열의 처음이나 중간에 새로 데이터가 삽입, 삭제시 그 부분만을 캐치하지 못한다. 그렇기 때문에 eslint에서도 에러가 나는 것이다. index를 key로 하는것은 지양해야한다.

배열의 index를 key로 사용하면 정말 안되는 것일까?

Robin Pokorny 말에 의하면 아래 3가지를 만족 할 경우 안심하고 index를 key로 써도 된다고 이야기 한다.

  • 배열과 각 요소가 수정, 삭제, 추가 등의 기능이 없는 단순 렌더링만 담당하는 경우
  • id로 쓸만한 unique 값이 없을 경우
  • 정렬 혹은 필터 요소가 없어야 함



어떤 값을 key로 사용하는 것이 좋은가

리액트는 상태가 바뀌면 이전 상태의 트리와 이후 상태의 트리를 비교한다. 이 때 key가 같다면 동일한 요소로 판단하고 업데이트 해준다.

배열의 순서나 내용이 변경되지 않는다면 아무 key나 사용해도 된다(다르다는 전제 하에). 하지만 순서나 내용이 지속적으로 변화되는 상황이라면 개별 요소를 특정할 수 있는 key를 사용해야 한다. 그렇지 않으면 매번 렌더가 발생하고 효율이 크게 떨어지기 때문이다!

항상 듣는 것이지만 유지보수에 좋은 코드를 만들자!

참조 📚


https://ko.reactjs.org/docs/lists-and-keys.html#gatsby-focus-wrapper
https://www.youtube.com/watch?v=ghxHAy3LH28
https://velog.io/@vlfflq2004/React-Index%EB%A5%BC-key%EB%A1%9C-%EC%93%B0%EB%A9%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0
https://ko.reactjs.org/docs/reconciliation.html#recursing-on-children

profile
RN App Developer

0개의 댓글