728x90

*하루동안 새롭게 알게된 부분, 에러를 해결한 방법 등을 작성하는 개발일기입니다. 다른 사람에게도 설명해줄 수 있도록 제 머릿속에 넣기 위해 정리를 시작하게 되었습니다. 

React에서 map 사용 시 key를 설정해줘야 하는 이유는

아래와 같이 컴포넌트를 반복하여 렌더링해줘야 하는 경우, map을 사용한다. 

 

 

 

그런데 이 때, 배열 내부의 엘리먼트에 key 값을 지정해주지 않으면, 'Each child in a list should have a unique key prop.' 경고문이 뜨게 된다. 

 

 

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

 

리액트는 state에서 변경된 부분만 찾아 리렌더링해주는데, 이때 가상 dom과 비교하여 바뀐 부분만 리렌더링해준다. 만약, 배열에 요소가 추가되었다면 배열 전체가 변경된 것이라고 생각하고 전체를 리렌더링 하게 된다. 마지막 요소만 변경되었으니, 전체를 리렌더링할 필요는 없는데도 말이다. 

 

그래서 배열 내부 엘리먼트에 key를 지정해줘야 한다. key 값을 지정해주면 리액트는 배열에 추가된 요소에 대해서만 리렌더링한다. 즉, key는 배열의 어떤 원소에 변동이 있었는지 알아내고자 할 때 사용되는 것이다. 따라서, 데이터가 가진 고유의 값을 key로 설정해야 한다. 

 

const PostList = ({ posts }) => {
    return(
        posts.map((post) => {
            return(
                <tr key={post.id}>
                    <td>{post.id}</td>
                    <td>{post.nickname}</td>
                    <td>{post.role}</td>
                    <td>{post.phone}</td>
                </tr>
            );
        })
    ); 
}

export default PostList; 

 

 

key 값으로 index를 설정하는 경우도 있는데, 어떤 경우에는 key 설정의 장점을 하나도 살리지 못하고 배열 전체가 리렌더링 될 수 있다.  배열에 첫 번째 위치에 새로운 element를 넣게 되면, 기존 배열의 index가 하나씩 밀리게 된다. 그럼 결국, 배열 전체가 변경되었다고 생각하기 때문에 배열 전체가 리렌더링 되는 것이다. 

 

// 기존 배열 
key 0, {id: 0, title: 'hello', content: 'olleh'}, 
key 1, {id: 1, title: 'my', content: 'ym'}, 
key 2, {id: 2, title: 'name', content: 'eman'}, 

// 배열 첫 번째 위치에 새로 element를 넣음 
key 0, {id: 3, title: 'is', content: 'si'}, 
key 1, {id: 0, title: 'hello', content: 'olleh'}, 
key 2, {id: 1, title: 'my', content: 'ym'}, 
key 3, {id: 2, title: 'name', content: 'eman'}, 

 

그래서, element를 고유하게 식별할 수 있는 unique한 값을 key로 설정해주는 게 좋다. 가장 사용하기 쉬운 것은 Database의 id이다. AUTO_INCREMENT된 id 값을 사용하거나, id가 아니라도 unique한 값이라면 key로 사용하면 된다. 

 

Robin Pokorny에 의하면, 아래 3가지를 만족하는 경우 index를 key로 써도 된다고 한다. (key 값으로 index를 꼭 설정해야겠다면, 아래의 조건을 확인하자)

  1. 배열과 각 요소가 static이며 computed 되지 않고, 변하지 않아야 한다. 
  2. 데이터 내부에 id로 쓸만한 unique 값이 없다. 
  3. 데이터가 결코 reordered 또는 filtered 되지 않는다. 
728x90

+ Recent posts