[React Docs 번역] Lists and Keys

김승엽
Berkbach
6 min readApr 19, 2020

--

Photo by Jozsef Hocza on Unsplash

📝 리스트와 Key

우선 JS에서 리스트를 변환하는 방법을 보겠습니다. 아래는 map() 함수를 이용해서 기존 배열의 값들을 2 곱하고 새로운 배열을 doubled 변수에 담는 예제입니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);

[2, 4, 6, 8, 10] 이 콘솔에 출력됩니다.

React에서 배열을 element의 리스트로 변환하는 것도 거의 비슷합니다.

다수 컴포넌트 렌더링

element 모음을 만들고 {} 를 사용해서 JSX안에 포함할 수 있습니다. 아래는 JS의 map() 함수를 이용해서 numbers 배열을 반복 실행합니다. 배열의 값 마다 <li> element를 리턴합니다. 그리고 element 배열을 listItems 변수에 담습니다.

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);

listItems 배열을 <ul> element 안으로 포함시키고 렌더링 하겠습니다.

ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);

이 코드는 1부터 5사이의 숫자 리스트를 보여줍니다.

기본 리스트 컴포넌트

흔히 컴포넌트 안에 element 리스트를 렌더링 합니다. 이전 예제를 컴포넌트로 바꾸는 작업을 하겠습니다.

이 코드를 실행하면 아래와 같은 경고 메세지를 콘솔에서 확인할 수 있습니다. 여기서 “key” 는 element 리스트를 만들 때 생성되는 특수한 문자 속성입니다.
Warning: Each child in a list should have a unique “key” prop.

numbers.map() 안의 element에 key 를 넣어서 이 이슈를 해결합시다.

🔑 Keys

key 는 React가 각 아이템이 변화, 추가, 삭제할지 확인하는 것을 도와줍니다. key 는 element의 안정적인 고유성을 위해 배열 안의 element에게 줘야합니다.

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);

key 를 정하는 방법 중 가장 좋은 것은 리스트의 다른 아이템 중에서 고유한 정체성을 가진 문자열을 사용하는 것입니다. 흔한 방법은 데이터의 ID 를 사용하는 것 입니다.

const todoItems = todos.map((todo) =>
<li keys={todo.id}>
{todo.text}
</li>
);

렌더링 된 아이템이 안정적인 ID 가 없을 때 최후의 수단으로 아이템의 인덱스를 key 로 사용할 수 있습니다.

const todoItems = todos.map((todo, index) =>
<li key={index}>
{todo.text}
</li>
);

아이템의 순서가 바뀐다면 key 를 인덱스로 지정하는 방식을 추천하지 않습니다. 성능에 안좋은 영향을 줄 수 있고 컴포넌트의 state 이슈를 불러올 수 있습니다. Robin Pokorny 의 관련 글을 확인해주세요.

Key로 컴포넌트 추출

key 는 주변 배열의 context에서만 의미가 있습니다. 예로 만약 ListItem 컴포넌트를 추출한다면 <li> element 대신 <ListItem /> element에서 key 를 유지해야합니다.

경험 상 map() 안의 element에게 key 를 주는 것이 좋습니다.

Key는 형제 사이에서만 고유한 값이어야 합니다.

key 는 배열 안에서 고유한 값이어야 하고 전체에서는 고유하지 않아도 됩니다. 다른 배열에서 같은 값의 key 를 사용해도 됩니다.

key 는 React에게 힌트를 제공하지만 컴포넌트로 전달하지 않습니다. 컴포넌트에서 같은 값이 필요하다면 다른 이름의 props로 전달하면 됩니다.

const content = posts.map((post) =>
<Post
key={post.id}
id={post.id}
title={post.title}
/>
);

위 예제에서 Post 컴포넌트는 props.id 를 읽을 수 있지만 props.key 는 읽지 못합니다.

JSX에서 map( ) 함수 포함하기

위 예제에서 별도의 listItems 변수를 선언하고 이를 JSX에 포함했습니다.

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<ListItem key={number.toString()} value={number} />
);
return <ul>{listItems}</ul>;
}

JSX에서 {} 를 쓰면 표현식을 쓸 수 있습니다. map() 을 인라인으로 써보겠습니다.

function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{
numbers.map((number) =>
<ListItem key={number.toString()} value={number} />
)
}
</ul>
);
}

때론 이 코드가 더 깔끔할 수 있습니다. 하지만 이 방식을 자주 사용하는 것은 좋지 않습니다. JS와 마찬가지로 가독성을 위해 변수로 추출 할지를 고민 해야 합니다. map() 이 중첩되면 컴포넌트를 추출하는 것이 좋을 수 있습니다.

📚 정리 및 참고 자료

  1. element를 리스트로 정의 할 때는 key 라는 속성을 지정해야 합니다.
  2. 같은 배열 안의 element는 고유한 key 값을 가져야 합니다.
  3. key 는 주변 배열의 context에서만 의미가 있습니다.

--

--