불변성 — 왜 직접 바꾸면 안 되고 새로 만들어야 할까?
Article
React에서 상태를 업데이트할 때, 이런 코드를 쓰면 화면이 바뀌지 않습니다.
const [items, setItems] = useState(["사과", "바나나"]);
function addItem() {
items.push("포도"); // 원본 배열을 직접 수정
setItems(items); // 화면이 안 바뀝니다!
}
분명 "포도"를 추가했는데 왜 화면이 안 바뀔까요? 여기서 등장하는 개념이 **불변성(Immutability)**입니다.
불변성이란
불변성은 원본을 직접 수정하지 않고, 새로운 복사본을 만들어서 수정하는 것입니다.
비유하자면, 문서를 수정할 때 원본 파일을 직접 고치는 게 아니라 복사본을 만들어서 그 복사본을 수정하는 것과 같습니다. 원본은 그대로 보존됩니다.
왜 React에서 불변성이 중요할까요
React가 리렌더링을 할지 말지 판단하는 방법을 알면 이해가 됩니다.
React는 상태가 바뀌었는지를 참조 비교로 확인합니다. 쉽게 말하면, "이전 값과 새 값이 같은 물건인가?"를 확인합니다. 값이 같은지가 아니라, 같은 물건(같은 메모리 주소)인지를 봅니다.
items.push("포도");
setItems(items);
이 코드에서 items 배열에 "포도"를 추가했지만, items라는 배열 자체는 같은 배열입니다. 내용물은 바뀌었지만 그릇은 그대로입니다.
React는 "같은 그릇이네? 바뀐 거 없나 보다" 하고 리렌더링을 건너뜁니다.
setItems([...items, "포도"]);
이렇게 하면 새 배열을 만들어서 전달합니다. React는 "새 그릇이네? 뭔가 바뀌었구나" 하고 리렌더링을 실행합니다.
배열 상태 업데이트
배열을 수정할 때 자주 쓰는 패턴을 정리합니다.
항목 추가
// 잘못된 방법
items.push("포도");
setItems(items);
// 올바른 방법
setItems([...items, "포도"]);
항목 삭제
// filter로 새 배열을 만듭니다
setItems(items.filter((item) => item !== "바나나"));
항목 수정
// map으로 새 배열을 만듭니다
setItems(items.map((item) =>
item === "사과" ? "청사과" : item
));
공통점이 보이나요? 전부 새 배열을 만들어서 setItems에 전달하고 있습니다. push, pop, splice 같은 원본을 직접 바꾸는 메서드는 사용하지 않습니다.
객체 상태 업데이트
객체도 마찬가지입니다. 스프레드 연산자(...)로 복사한 뒤 수정합니다.
const [user, setUser] = useState({ name: "민초리", age: 20 });
// 잘못된 방법
user.age = 21;
setUser(user);
// 올바른 방법
setUser({ ...user, age: 21 });
{ ...user, age: 21 }는 "user의 모든 속성을 복사하되, age만 21로 덮어쓴" 새 객체를 만듭니다.
비유: 택배 상자
택배 기사가 물건을 확인할 때, 상자 안을 열어보지 않고 상자가 바뀌었는지만 확인한다고 생각해보세요.
- 같은 상자에 내용물만 바꿔 넣으면 → "같은 상자네? 변화 없음!" (리렌더링 안 함)
- 새 상자에 내용물을 옮겨 담으면 → "새 상자네? 확인해봐야겠다!" (리렌더링 함)
React의 참조 비교가 바로 이 방식입니다. 효율적이지만, 대신 우리가 새 상자를 만들어줘야 합니다.
정리
- 불변성은 원본을 직접 수정하지 않고 새 복사본을 만드는 것입니다.
- React는 참조 비교로 변경을 감지하기 때문에, 같은 객체/배열을 수정하면 변경을 알아채지 못합니다.
- 배열은 스프레드 연산자, filter, map으로 새 배열을 만들어 업데이트합니다.
- 객체는 스프레드 연산자로 복사한 뒤 수정합니다.
push,pop,splice같은 원본을 바꾸는 메서드는 상태 업데이트에서 사용하지 않습니다.
이번 글까지 React의 핵심 기초 개념을 다루었습니다. 브라우저 렌더링부터 가상DOM, 컴포넌트, 상태, 불변성까지 — 이 개념들이 서로 연결되어 React의 동작 원리를 이루고 있습니다.