말그대로 불변, 변하지않는 성질이라는 것인데 리액트에서는 메모리에 있는 값을 변경할 수 없는 것을 의미한다. 자바스크립트의 데이터 형태중에 원시 데이터는 불변성을 가지고, 원시 데이터가 아닌 객체, 배열, 함수는 불변성을 가지지 않는다.
이게 왜 문제가 되는가?
1. 예측 불가능한 코드 : 데이터 구조를 직접 변경하면, 프로그램의 다른 부분에서 변경한 데이터를 참조하고 있을 때 참조하는 부분이 예상치 못한 방향으로 변경될 수 있기 때문에 예상치 못한 버그를 유발한다.
2. 버그 추적의 어려움: 원본 데이터가 여러 곳에서 변경된다면, 어떤 부분의 코드가 변경되었는지 알기 힘들어진다.
기존 데이터의 불변성을 유지하기 위해서는 새로운 데이터를 만든다! 새로운 데이터를 만들어 메모리 주소의 변화를 준다.
예시)
let numbers = [1, 2, 3];
let newNumbers = [...numbers, 4]; // 새 배열을 생성하여 기존 배열을 변경하지 않음
console.log(numbers); // [1, 2, 3]
console.log(newNumbers); // [1, 2, 3, 4]
리액트에서는 화면을 다시 렌더링 할지 말지 고민하는 여부를 state의 변화를 통해 확인한다고 한다. state가 변했다면 리렌더링을 진행하고, 그렇지 않으면 하지 않는다.
이때 state의 변화를 확인하는 방법이 메모리 주소의 변경을 확인하는 것이다. 때문에 push()
같은 함수로 원본 데이터의 불변성을 깨고 직접적인 변화를 준다면 메모리 주소가 변한것이 아니기 때문에 리렌더링이 일어나지 않는다. 그렇기 때문에 기존 값을 복사한 후에 새로운 값을 더하거나 수정하는 방식으로 state를 관리한다.
import React, { useState } from "react";
function App() {
const [count, setCount] = useState([1]);
function onClickHandler() {
// spread operator를 통해서 배열을 복사하고 그 뒤에 2를 추가해줌
setDogs([...count, 2]);
}
console.log(count); // [1,2]
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
오랜만에 리액트를 사용하게 되었다. 리액트 실습 주차로 넘어오고 나서 강의를 듣는데 이런 불변성과 state의 상관 관계를 알게 된건 처음이었다. 메모리 주소의 변경을 통해 state의 변경을 확인하는 점을 알게 되어서 또 하나 배워간다는 느낌이 들었다. 그전까진 멋모르고 사용했던 useState를 더 자세히 알고나서 사용할 수 있게 되겠다 생각했다.
썸네일 출처: 위키백과
이기성을 부캠 튜터로!🫡