React에서 배열을 렌더링할 때 key를 사용하는 이유는 성능 최적화와 UI의 안정성을 위해 매우 중요합니다. key는 React가 각 요소를 고유하게 식별할 수 있도록 하는 특수 속성입니다.
React는 Virtual DOM을 사용하여 UI를 효율적으로 업데이트합니다. key는 React가 어떤 항목이 변경, 추가 또는 제거되었는지 식별하는 데 도움을 줍니다. 이를 통해 React는 최소한의 DOM 조작으로 UI를 업데이트할 수 있습니다.
Diffing 알고리즘: React는 Virtual DOM의 이전 상태와 새로운 상태를 비교(diffing)하여 변경 사항을 파악합니다. key를 사용하면 React는 각 요소를 고유하게 식별할 수 있으므로, 요소 간의 비교가 간단해지고, 변경 사항을 효율적으로 처리할 수 있습니다.
컴포넌트의 상태와 생명주기 메서드는 key에 따라 유지됩니다. key가 없거나 잘못된 경우, React는 요소의 순서를 추적하지 못해 컴포넌트의 상태가 예기치 않게 초기화되거나 유지되지 않을 수 있습니다.
key가 없으면 React는 요소의 순서를 추적하지 못해 요소가 재사용되지 않고, 매번 새로운 요소로 간주됩니다. 이는 컴포넌트의 상태가 의도하지 않게 초기화되는 문제를 일으킬 수 있습니다.
배열의 요소가 변경될 때, 예를 들어 항목이 추가되거나 제거될 때, key는 요소의 일관성을 유지하는 데 도움을 줍니다. key를 사용하면 React는 항목의 위치를 추적하여 올바르게 추가, 삭제 및 업데이트할 수 있습니다.
리스트 항목 업데이트: key를 사용하면 React는 각 항목의 위치를 추적하여, 리스트 항목이 업데이트될 때 불필요한 재렌더링을 피하고, 필요한 부분만 업데이트합니다.
다음은 key를 사용하는 예시 코드입니다.
import React from 'react';
function ItemList({ items }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
export default ItemList;
위 코드에서 item.id는 각 항목을 고유하게 식별할 수 있는 key입니다. key는 일반적으로 고유한 ID나 배열의 인덱스를 사용합니다.
우리는 입력 필드를 포함하는 리스트 컴포넌트를 만들고, 사용자가 각 필드에 입력한 값을 유지하고자 합니다. key를 올바르게 사용하지 않으면, 항목을 추가하거나 삭제할 때 입력된 값이 예기치 않게 초기화될 수 있습니다.
import React, { useState } from 'react';
function App() {
const [items, setItems] = useState([{ id: 1, text: '' }, { id: 2, text: '' }]);
const handleAddItem = () => {
setItems([...items, { id: items.length + 1, text: '' }]);
};
const handleInputChange = (index, value) => {
const newItems = [...items];
newItems[index].text = value;
setItems(newItems);
};
return (
<div>
<button onClick={handleAddItem}>Add Item</button>
{items.map((item, index) => (
<div key={index}>
<input
type="text"
value={item.text}
onChange={(e) => handleInputChange(index, e.target.value)}
/>
</div>
))}
</div>
);
}
export default App;
이 코드에서 key로 인덱스를 사용했습니다. 이로 인해 항목이 추가되거나 삭제될 때 상태가 올바르게 유지되지 않을 수 있습니다.
import React, { useState } from 'react';
function App() {
const [items, setItems] = useState([{ id: 1, text: '' }, { id: 2, text: '' }]);
const handleAddItem = () => {
setItems([...items, { id: items.length + 1, text: '' }]);
};
const handleInputChange = (id, value) => {
setItems(items.map(item => item.id === id ? { ...item, text: value } : item));
};
return (
<div>
<button onClick={handleAddItem}>Add Item</button>
{items.map((item) => (
<div key={item.id}>
<input
type="text"
value={item.text}
onChange={(e) => handleInputChange(item.id, e.target.value)}
/>
</div>
))}
</div>
);
}
export default App;
이 코드에서는 각 항목의 고유한 id를 key로 사용했습니다. 이로 인해 항목이 추가되거나 삭제될 때 입력 필드의 상태가 올바르게 유지됩니다.
첫 번째 코드에서 "Add Item" 버튼을 눌러 새 항목을 추가하면, 기존 항목에 입력한 텍스트가 초기화되거나 다른 필드로 이동하는 현상을 볼 수 있습니다.
두 번째 코드에서 "Add Item" 버튼을 눌러 새 항목을 추가하면, 기존 항목에 입력한 텍스트가 그대로 유지됩니다.
이 예시는 key를 잘못 사용했을 때 발생할 수 있는 문제를 잘 보여줍니다. key를 고유하게 설정하면 React가 각 요소를 정확히 추적하여 상태를 안정적으로 유지할 수 있습니다. key로 인덱스를 사용하면 요소의 순서가 바뀌거나 새로운 요소가 추가될 때 문제가 발생할 수 있습니다. 고유한 식별자를 사용하여 이러한 문제를 방지해야 합니다.
React에서 배열을 렌더링할 때 key를 사용하는 것은 성능 최적화, 안정적인 컴포넌트 상태 유지, 일관된 UI 업데이트를 위해 필수적입니다. key는 각 요소를 고유하게 식별하여 React가 효율적으로 UI를 업데이트할 수 있도록 도와줍니다. 이를 통해 사용자에게 더 나은 성능과 일관된 경험을 제공할 수 있습니다.