[React] 왜 불변성을 유지해줘야 하나?
불변성이란?
불변성은 상태를 변경하지 않는 것
을 의미한다. 다음 코드를 보면서 불변성에 대해 알아보자.
let a = 3;
위 코드는 아래와 같이 메모리 공간 어딘가에 그 값이 저장되어 있을 것이다. 만약 이 변수의 상태, 즉 값을 다른 값으로 할당하게 되면, 불변성은 깨지게 된다.
React가 불변성을 유지하려고 하는 이유는?
리액트에서는 다음 두 가지의 이유로 불변성을 유지하라고 한다.
- 의도하지 않은 특정 객체가 변경되면, 참조하고 있던 객체에서도 변경이 일어난다. 이 상태를 유지할 경우, side-effect가 발생할 수도 있고, 프로그램의 복잡도도 높아진다.
- 변경이 일어난 객체의 프로퍼티만 비교함으로써, 최적화가 가능해진다.
불변성을 해치면서 상태의 값을 변경하려고 하면?
위와 같은 입력 폼에, 입력을 마친 후 추가 버튼을 눌러 아래 리스트에 목록을 추가하려고 한다.
userList state 를 직접 건드려 요소를 추가한 뒤, setter의 인자로 state 원본을 전달해보자.
userList.push(user);
setUserList(userList);
setter를 호출하기 전과 후에 로그를 찍어봤다. userList state 에 값은 제대로 들어갔다. setter 를 호출한 뒤 리렌더링을 기대하지만, 되지 않는다.
그렇다면 분명 state 의 값이 바꼈는데도 불구하고, 왜 렌더링은 다시 이뤄지지 않는 것일까?
React는 state의 변경을 어떻게 알아차릴까?
const prevState = [
{
id: 1,
name: "Kim",
age: 28,
},
];
let nextState = [
{
id: 1,
name: "Kim",
age: 28,
},
{
id: 2,
name: "Lee",
age: 29,
},
];
위와 같이, 배열에 들어있는 객체를 하나 하나 비교해가면서 변경 사항이 있는 지를 확인하는 데엔 오랜 시간이 걸릴 것이다. 만약 배열이 참조하고 있는 레퍼런스만 달라진다면, 레퍼런스만을 비교해서 변경사항이 발생했는 지 알아차릴 수 있다.
prevState == nextState;
React 는 레퍼런스 비교로 state 의 변경을 알아차린다. 따라서, 기존과 다른 주소를 참조하는 새로운 객체에 값을 담아 setter 를 호출해야 리액트 엔진은 둘이 다른 주소를 참조하니 state가 달라졌구나!
라고 생각하게 되는 것이다. 이후 리액트 요소 트리로 변환해 달라진 부분을 캐치해(없다면 말고) DOM 을 다시 그리게 되는 것이다.
댓글남기기