[React] 왜 불변성을 유지해줘야 하나?

1 분 소요

불변성이란?

불변성은 상태를 변경하지 않는 것 을 의미한다. 다음 코드를 보면서 불변성에 대해 알아보자.

let a = 3;


위 코드는 아래와 같이 메모리 공간 어딘가에 그 값이 저장되어 있을 것이다. 만약 이 변수의 상태, 즉 값을 다른 값으로 할당하게 되면, 불변성은 깨지게 된다.

http://dl.dropbox.com/s/re46qz7l5ya8a9l/React-%EC%99%9C%20%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%84%20%EC%9C%A0%EC%A7%80%ED%95%B4%EC%A4%98%EC%95%BC%20%ED%95%98%EB%82%98-1.png


React가 불변성을 유지하려고 하는 이유는?

리액트에서는 다음 두 가지의 이유로 불변성을 유지하라고 한다.

  1. 의도하지 않은 특정 객체가 변경되면, 참조하고 있던 객체에서도 변경이 일어난다. 이 상태를 유지할 경우, side-effect가 발생할 수도 있고, 프로그램의 복잡도도 높아진다.
  2. 변경이 일어난 객체의 프로퍼티만 비교함으로써, 최적화가 가능해진다.


불변성을 해치면서 상태의 값을 변경하려고 하면?

http://dl.dropbox.com/s/z7b6jhcnvf04409/React-%EC%99%9C%20%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%84%20%EC%9C%A0%EC%A7%80%ED%95%B4%EC%A4%98%EC%95%BC%20%ED%95%98%EB%82%98-2.png

위와 같은 입력 폼에, 입력을 마친 후 추가 버튼을 눌러 아래 리스트에 목록을 추가하려고 한다.


userList state 를 직접 건드려 요소를 추가한 뒤, setter의 인자로 state 원본을 전달해보자.

userList.push(user);
setUserList(userList);


setter를 호출하기 전과 후에 로그를 찍어봤다. userList state 에 값은 제대로 들어갔다. setter 를 호출한 뒤 리렌더링을 기대하지만, 되지 않는다.

http://dl.dropbox.com/s/5h0djopa3709ha5/React-%EC%99%9C%20%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%84%20%EC%9C%A0%EC%A7%80%ED%95%B4%EC%A4%98%EC%95%BC%20%ED%95%98%EB%82%98-3.png


그렇다면 분명 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 을 다시 그리게 되는 것이다.

카테고리:

업데이트:

댓글남기기