리액트에서 불변성을 지키는 이유

리액트에서 불변성을 지키는 이유

2024-02-25

자바스크립트에서 원시타입(primitive data type)은 변경 불가능한(immutable)한 값이다.

변경이 불가능하다라는 뜻은 메모리 영역에서의 변경이 불가능하다는 뜻이며, 재할당은 가능하다.


원시타입 이외의 모든 값은 Object(객체)이다. 객체는 변경 가능한(mutable)한 값이다. 객체는 변경 가능한(mutable)값이기 때문에 새로운 값을 다시 만들 필요없이 직접 변경이 가능하다.

let string = "hello";
string = "world";

string 변수에 "hello"라는 문자열을 할당하고, 다시 "world"라는 문자열을 할당했다. 이때, 첫번째 문자열은 메모리에서 사라지고, 새로운 문자열이 메모리에 할당된다.

let string = "hello";
let string2 = string.slice(0, 3);

// string = "hello"
// string2 = "hel"

string 변수에 "hello"라는 문자열을 할당하고, string2 변수에 string 변수의 문자열을 복사하여 할당했다. 이때, string 변수의 문자열은 변경되지 않는다.


let arr = [];

let arr2 = arr.push(1);

// arr = [1]

배열은 객체이기 때문에 변경이 가능하다. 위의 코드에서 arr.push(1)을 통해 arr 배열에 1이라는 원소가 추가되었다. 이때, arr 배열은 변경된다. 복사본을 리턴하는 메소드가 아닌 push, pop, shift, unshift, splice 등의 메소드는 원본 배열을 변경한다.

let object = {
  name: "been",
};

let object2 = object;

object2.name = "been2";

console.log(object.name); // been2

객체는 변경이 가능하기 때문에 object2 변수에 object 변수를 할당하고, object2.name을 변경하면 object.name도 변경된다. object도 동시에 변경되는 이유는 object2에 object를 할당할 때, object2는 object의 메모리 주소를 참조하기 때문이다.

object에서 불변성을 유지하는 방법은 새로운 객체를 생성하여 값을 할당하는 방법이다.


불변성을 유지하는 방법

let object = {
  name: "been",
};

let object2 = {
  ...object,
  name: "been2",
};

console.log(object.name); // been

object2에 object를 복사하여 새로운 객체를 생성하고, name을 변경하였다. 이때, object는 변경되지 않는다.


리액트에서 불변성을 지키는 이유

리액트를 사용해 개발을 할 때 useState 등을 사용해 상태를 관리 할 때 push, pop, shift, unshift 등의 메소드를 사용하지 않고, 새로운 배열을 만들어서 상태를 변경하며 자연스럽게 불변성을 지키며 개발을 했다.

리액트에서는 상태값을 업데이트 할 때 얕은비교를 수행해 이전 상태(참조값)와 새로운 상태(참조값)를 비교 한다. 새로운 참조값을 가진 Object를 생성하므로 이전 참조값에 영향을 주지 않는다.

  1. 불변성을 지키면 상태값을 업데이트 할 때 이전 상태와 새로운 상태를 비교하여 변경된 부분만 업데이트 하기 때문에 성능적으로 이점이 있다.
  2. 상태가 의도치않게 변경되는 것을 막을 수 있고, 사이드 이펙트를 사전에 방지하고 예측 가능한 코드를 작성할 수 있다.
const [state, setState] = useState(1);

// 불변성을 지키지 않은 상태 업데이트
  state = 2;
  setState(state);

// 불변성을 지킨 상태 업데이트
  setState(2);
const [state, setState] = useState([1, 2, 3]);

// 불변성을 지키지 않은 상태 업데이트
  state.push(4);
  setState(state);

// 불변성을 지킨 상태 업데이트
  setState([...state, 4]);
const [state, setState] = useState({
  name: "been",
  age: 32,
});

// 불변성을 지키지 않은 상태 업데이트
  state.name = "been2";
  setState(state);

// 불변성을 지킨 상태 업데이트
  setState({
    ...state,
    name: "been2",
  });

이처럼 리액트로 개발을 할 때 불변성을 유지함으로써 안정성을 유지하고 성능을 향상시킬 수 있다.