ReactJS - 키: 효율적인 목록 렌더링의 힘을 해제하는 열쇠

안녕하세요, 미래의 React 슈퍼스타 여러분! 오늘 우리는 React에서 가장 중요한 개념 중 하나인 키에 대해 배울 것입니다. 프로그래밍에 새로운 사람이라면 걱정하지 마세요 - 저는 여러분을 단계별로 안내할 것입니다. 수년 동안 수많은 학생들을 가르친 경험을 바탕으로 말이죠. 그럼 커피(또는 차, 당신이 좋아하는 음료라면)를 한 잔 챙겨서, 이 흥미로운 여정에 함께 동참해 보세요!

ReactJS - Keys

목록과 키 이해하기

React에서 목록이란?

키에 대해 이야기하기 전에, 먼저 목록에 대해 이야기해 보겠습니다. React에서 우리는 종종 페이지에 여러 개의 유사한 항목을 표시해야 합니다. 예를 들어, 할 일 목록, 쇼핑 카트, 또는 당신의 좋아하는 영화 목록을 생각해 보세요. React에서는 이러한 목록을 표현하기 위해 JavaScript 배열을 사용하고, 이를 컴포넌트에서 렌더링합니다.

간단한 예제를 보겠습니다:

function MovieList() {
const movies = ['Inception', 'Interstellar', 'The Dark Knight'];

return (
<ul>
{movies.map(movie => <li>{movie}</li>)}
</ul>
);
}

이 코드에서 우리는 map 함수를 사용하여 영화 제목의 배열을 <li> 요소의 배열로 변환하고 있습니다. 꽤 쉬운东西이죠?

키 프로프 Enter

이 코드를 실행하면 콘솔에 다음과 같은 경고 메시지를 볼 수 있습니다:

Warning: Each child in a list should have a unique "key" prop.

이제 우리의 스타가 등장합니다 - key 프로프입니다!

키는 무엇인가요?

키는 React가 목록의 어떤 항목이 변경되었는지, 추가되었는지, 또는 제거되었는지 식별하는 데 도움을 주는 특별한 문자열 속성입니다. 목록의 각 항목에 고유한 이름 태그를 달아주는 것과 같습니다.

우리의 이전 예제를 수정하여 키를 포함시키겠습니다:

function MovieList() {
const movies = [
{ id: 1, title: 'Inception' },
{ id: 2, title: 'Interstellar' },
{ id: 3, title: 'The Dark Knight' }
];

return (
<ul>
{movies.map(movie => <li key={movie.id}>{movie.title}</li>)}
</ul>
);
}

이제 각 <li> 요소에 고유한 key 프로프가 있습니다. React는 이 키를 사용하여 목록이 변경될 때 효율적으로 업데이트합니다.

키의 마법

키가 왜 중요한가요?

키를 사용하면 React가 다음과 같은 작업을 수행하는 데 도움이 됩니다:

  1. 목록의 항목이 변경되었는지, 추가되었는지, 제거되었는지 식별
  2. 재랜더링 사이의 컴포넌트 상태 유지
  3. DOM 조작을 최소화하여 성능 향상

적절한 키 선택

이제 "키로 무엇을 사용해야 할까요?"라는 질문이 드는 것 같습니다. 훌륭한 질문입니다! 다음과 같이 설명드리겠습니다:

  1. 고유하고 안정적인 ID 사용: 데이터가 데이터베이스에서 오는 경우, 항목의 ID를 키로 사용합니다.
<li key={item.id}>{item.name}</li>
  1. 항목의 인덱스를 마지막 수단으로 사용: 안정적인 ID가 없는 경우, 배열의 인덱스를 사용할 수 있습니다. 하지만 목록이 재정렬될 수 있다면 문제가 발생할 수 있습니다.
{items.map((item, index) => <li key={index}>{item.name}</li>)}
  1. 고유한 키 생성: 항목을 실시간으로 생성하는 경우, uuid와 같은 패키지를 사용하여 고유한 키를 생성할 수 있습니다.
import { v4 as uuidv4 } from 'uuid';

{items.map(item => <li key={uuidv4()}>{item.name}</li>)}

키와 인덱스: 좀 더 깊이 탐구하기

이제 기본 개념을 이해했으므로, 인덱스를 키로 사용하는 것에 대해 좀 더 깊이 탐구해 보겠습니다.

인덱스를 키로 사용할 때

인덱스를 키로 사용하는 것은 유혹적입니다. 왜냐하면 그것이 간편하고 언제나 사용 가능하기 때문입니다. 그러나 다음과 같은 경우에만 사용하는 것이 좋습니다:

  1. 목록이 정적이고 변경되지 않을 때
  2. 목록의 항목에 안정적인 ID가 없을 때
  3. 목록이 재정렬되거나 필터링되지 않을 때

인덱스를 키로 사용하는 것이 적절한 예제:

function StaticList() {
const items = ['Apple', 'Banana', 'Cherry'];

return (
<ul>
{items.map((item, index) => <li key={index}>{item}</li>)}
</ul>
);
}

인덱스를 키로 사용하는 위험

다음과 같은 동적인 예제를 통해 인덱스를 키로 사용하는 것이 문제가 될 수 있는 이유를 이해해 보겠습니다:

function DynamicList() {
const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']);

const addItem = () => {
setItems(['New Item', ...items]);
};

return (
<>
<button onClick={addItem}>Add Item</button>
<ul>
{items.map((item, index) => (
<li key={index}>
{item}
<input type="text" />
</li>
))}
</ul>
</>
);
}

이 예제에서 새 항목을 추가하고 입력 필드에 무언가를 입력한 후, 입력 값이 섞이는 것을 발견할 수 있습니다. 이는 React가 인덱스를 키로 사용하고 있기 때문입니다.

더 나은 접근 방식

이 문제를 해결하기 위해, 우리는 안정적이고 고유한 식별자를 사용해야 합니다:

function DynamicList() {
const [items, setItems] = useState([
{ id: 1, text: 'Item 1' },
{ id: 2, text: 'Item 2' },
{ id: 3, text: 'Item 3' }
]);

const addItem = () => {
const newItem = { id: Date.now(), text: 'New Item' };
setItems([newItem, ...items]);
};

return (
<>
<button onClick={addItem}>Add Item</button>
<ul>
{items.map(item => (
<li key={item.id}>
{item.text}
<input type="text" />
</li>
))}
</ul>
</>
);
}

이제 새 항목을 추가하거나 목록을 재정렬해도 React가 각 항목을 정확하게 추적할 수 있습니다.

결론

축하합니다! React에서 키의 힘을 해제했습니다. 키는 목록 항목에 이름 태그를 달아주는 것과 같아서, React가 특정 항목을 추적하는 데 도움을 줍니다.

이제 우리가 배운 내용을 요약해 보겠습니다:

개념 설명
React 목록 항목의 특별한 문자열 속성
목적 목록의 변경 사항을 효율적으로 식별
가장 좋은 관행 안정적이고 고유한 식별자를 키로 사용
인덱스를 키로 사용 정적이고 변경되지 않는 목록에만 사용
이점 성능 향상과 컴포넌트 상태 유지

키를 계속 연습하면, 곧 동적인 React 애플리케이션을 효율적으로 만들 수 있을 것입니다. 행복하게 코딩하세요, React의 세상에서 각 항목은 고유한 키를 가지고 있어야 합니다!

Credits: Image by storyset