React에서 상태 관리와 데이터 변경을 다룰 때, 깊은 복사 (Deep Copy)와 얕은 복사 (Shallow Copy)의 개념은 매우 중요합니다. 이러한 복사 방식은 주로 불변성 (Immutability)을 지키는 데 사용되며, React의 성능과 렌더링 효율성을 높이는 데 큰 역할을 합니다.
null
, undefined
와 같은 타입을 포함합니다. 원시 타입은 값 자체를 저장하고, 변수에 값을 할당해도 다른 변수에는 영향을 주지 않습니다.let a = 10;
let b = a;
b = 20;
console.log(a); // 10
console.log(b); // 20
a
와 b
는 독립적인 값으로, 하나를 변경해도 다른 변수에는 영향을 미치지 않습니다.let obj1 = { name: 'Alice' };
let obj2 = obj1;
obj2.name = 'Bob';
console.log(obj1.name); // 'Bob'
console.log(obj2.name); // 'Bo
obj1
과 obj2
는 같은 객체를 참조하고 있기 때문에, 하나를 수정하면 다른 것도 변경됩니다.얕은 복사는 객체의 1단계만 복사하고, 중첩된 객체는 여전히 원본 객체와 동일한 참조를 공유합니다. 이 말은 중첩된 객체나 배열에 변경이 일어나면 원본 객체에 영향을 미친다는 뜻입니다.
const clubInfo = {
name: 'COW Club',
members: [
{ name: 'John', fee: 100, part: 'Server', isAttending: true },
{ name: 'Sara', fee: 150, part: 'Web', isAttending: false }
]
};
const newClubInfo = { ...clubInfo }; // 얕은 복사
// 중첩된 객체는 여전히 참조를 공유
newClubInfo.members[0].fee = 200;
console.log(clubInfo.members[0].fee); // 200
console.log(newClubInfo.members[0].fee); // 200
newClubInfo
는 clubInfo
의 얕은 복사본을 만들었지만, members
배열 안의 객체는 여전히 같은 메모리 주소를 참조하고 있습니다. 따라서 newClubInfo.members[0]
을 수정하면 clubInfo.members[0]
에도 영향을 미칩니다.깊은 복사는 객체의 모든 중첩된 속성까지 독립적으로 복사하는 방식입니다. 깊은 복사를 사용하면 원본 객체와 복사본 객체가 서로 영향을 미치지 않습니다.
const clubInfo = {
name: 'COW Club',
members: [
{ name: 'John', fee: 100, part: 'Server', isAttending: true },
{ name: 'Sara', fee: 150, part: 'Web', isAttending: false }
]
};
const deepCopyClubInfo = JSON.parse(JSON.stringify(clubInfo)); // 깊은 복사
// 깊은 복사본에서 변경
deepCopyClubInfo.members[0].fee = 200;
console.log(clubInfo.members[0].fee); // 100
console.log(deepCopyClubInfo.members[0].fee); // 200
JSON.parse(JSON.stringify())
방법은 객체의 깊은 복사를 수행합니다. 이 방식은 객체 내부의 모든 속성을 복사하고, 원본 객체와 복사본이 완전히 독립적인 객체로 존재합니다.React에서는 상태를 직접 수정하지 않고, 새로운 객체를 생성하여 상태를 업데이트해야 합니다. 이 과정에서 불변성(Immutability)을 지키는 것이 매우 중요합니다. 불변성을 지키면 React가 상태 변화(예: setState
)를 쉽게 추적하고, 효율적인 리렌더링을 할 수 있습니다.
const [members, setMembers] = useState([
{ name: 'John', fee: 100, part: 'Server', isAttending: true },
{ name: 'Sara', fee: 150, part: 'Web', isAttending: false }
]);
// 불변성을 유지하면서 상태 업데이트
const updateFee = (index, newFee) => {
const updatedMembers = [...members]; // 얕은 복사
updatedMembers[index] = { ...updatedMembers[index], fee: newFee }; // 중첩 객체 복사
setMembers(updatedMembers); // 새로운 배열로 상태 업데이트
};
Object.assign()
JSON.parse(JSON.stringify())
...
(스프레드 연산자)slice()
const newObj = { ...obj };
const newObj = obj;
const newObj = Object.assign({}, obj);
const newObj = JSON.parse(JSON.stringify(obj));