key에 그냥 index를 써주면 왜 안될까?
리액트를 사용하다보면 map 함수를 정말 많이 사용한다. 객체.map()
map을 돌려서 각 객체수 만큼 요소들을 렌더링할 때 각 요소들에 고유한 key값을 주지 않으면 경고가 뜬다.
그런데 코드 리뷰를 받은 것 중에 key 값을 흔히 index로 많이 넣고는 하는데
${item}-{index} 등 말그대로 고유한 키값을 줄 것을 권장해주셔서 그 이유에 대해 궁금해졌다.
일단 key 자체는 왜 필요할까?
key는 react가 어떤 항목을 변경, 추가, 삭제할 지 식별하는 것을 도와준다.
react는 업데이트 요소들을 기존의 요소들과 비교 후 변경하는데 이때 key로 식별을 하기 때문에
해당 엘리먼트에 고유성을 부여해 그 고유성을 비교해서 렌더링을 효과적으로 수행할 수 있다.
그럼 key에 index를 넣어주면 왜 안될까?
배열의 순서나 내용이 변경되지 않는다면 아무런 key값을 사용해도 무방하다!
하지만 순서가 지속적으로 변화되는 상황이라면
개별 요소를 감지할 수 있는 고유한 key값을 사용해야 한다.
그렇지 않으면 순서를 하나만 바꾸어도 인덱스에 해당하는 값이 다 바뀌니까
전체를 렌더링해서 렌더링의 성능 저하를 일으킬 수 있기 때문이다.
그러면 uuid 라이브러리 사용하면 안되나? 라는 생각이 들었다.
그래서 검색을 해보니 uuid를 이미 사용해보신 분이 계셨다.
그런데 고유한 값을 부여하는 것은 해결이 되었지만 배열이 변경된 경우 동일한 콘텐츠를 가진 요소의 uuid가 다시 생성이 된다.
리액트에서는 key를 한 번 할당하면 목록의 모든 항목이 매번 동일한 키를 받는 것이 이상적이다.
왜냐하면 매번 키가 새로 생성되면 React가 가상 Dom을 조정할 때 데이터 변경을 최적화 할 수 없기 때문이다.
그래서 생겨난게 key의 개념인것인데,,! 이 문제를 다시금 일으키는 것이 uuid 같은 라이브러리라는 것
그래서 uuid와 비슷한 라이브러리 nanold의 공식 문서에는 리액트에서 사용하지 않을 것을 권장한다고 써있기도 하다.
그러면 뭐를 쓸까...?
각 객체의 id값이 있다면 id값을 key로 사용하자. '변하지 않고 유일한 값인' id값
그런데 사용할 id가 없다면?? 최후의 수단으로 index를 사용하고,,
이 또한 ${text}-{index}처럼 다른 컴포넌트와 겹치지 않을 고유한 key 값을 사용해주자!!