React
React의 상태 비교와 setState()
shuai
2025. 8. 23. 14:01
React는 성능 때문에 참조(주소)만 비교한다. 즉, 상태가 변경되었는지 확인할 때 깊은 비교를 하지 않고, 참조를 기준으로만 확인한다.
즉, 상태가 이전과 같은 객체나 배열을 참조하고 있으면 변경 없음이라고 판단해서 리렌더링 하지 않는다. 반대로, 같은 내용을 가진 객체라도 새로운 객체를 만들어 넣으면 참조가 달라졌다고 판단해서 리렌더링이 일어난다.
예를 들어, 아래의 코드를 비교해보자.
// 잘못된 방식 ❌ (원본 객체 수정)
setState(prev => {
prev.value = 2; // 기존 객체를 직접 수정
return prev; // 같은 참조 반환
});
// 올바른 방식 ✅ (새 객체 생성)
setState(prev => {
return { ...prev, value: 2 }; // 새로운 객체 생성
});
문득 setState()를 구현하던 중, 원본 객체를 수정하면 되는데 왜 새로운 객체를 만들어서 return 하는 방식을 취해야할까에 대한 의문이 생겼었다. 아래와 같은 상황이었다.
행 체크박스가 있는 테이블에서 특정 행의 isChecked 값을 toggle 해야했다. 값을 바꿔야 한다면, 어차피 객체이기 때문에 간단하게 인자값으로 넘어온 객체를 바로 수정하면 되지 않을까 하는 의문이 들었다.
setCheckedWarehouseTables((prev: any[]) => {
const found = prev.find((t) => t.id === id);
if (found) {
found.isChecked = next; // ❌ 객체 직접 수정
}
return prev; // ❌ 같은 배열 참조 반환
});
하지만, 위에서 살펴보았듯이 이렇게 되면 얕은 복사가 되기 때문에 React가 변경을 감지하지 못해서 리렌더링이 발생하지 않는다. 따라서, map을 사용하여 새로운 배열을 반환하도록 구현해야 한다.
setCheckedWarehouseTables((prev: any[]) =>
prev.map((t) =>
t.id === id ? { ...t, isChecked: next } : t
)
);