WEB/React

불변성

Harimad 2022. 4. 14. 17:15

🤔기존의 값을 직접 수정하지 않으면서 새로운 값을 만들어 내는 것을 '불변성을 지킨다'고 한다.

다음 예시 코드에서 어떻게 불변성을 지키는지 보자.

예시코드

const array = [1, 2, 3, 4, 5];

const nextArrayBad = array; // 배열 복사X, 똑같은 배열 참조
nextArrayBad[0] = 100;
console.log(array === nextArrayBad); // 똑같은 배열이기 때문에 true

const nextArrayGood = [...array]; // 배열 내부의 값을 모두 복사
nextArrayGood[0] = 100;
console.log(array === nextArrayGood); // 다른 배열이기 때문에 false

const object = {
  foo: 'bar',
  value: 1
}

const nextObejctBad = object; // 객체 복사X, 똑같은 객체 참조
nextObjectBad.value = nextObjectBad.value + 1;
console.log(object ===nextObjectBad); // 똑같은 객체라서 때문에 true

const nextObjectGood = {
  ...object,  // 기존에 있던 내용 모두 복사
  value: object.vlaue + 1  // 새로운 값을 덮어 씀
};

console.log( object === nextObjectGood); // 다른 객체라서 false

 

불변성을 지키지 않으면 객체 내부의 값이 새로워져도 리액트는 바뀐 것을 감지하지 못한다.
그러면 React.memo에서 서로 비교하며 최적화화는 것이 불가능해진다.



추가적으로, 전개 연산자(spread operator)를 이용해서 객체나 배열 내부의 값을 복사할 때는
얕은 복사(shallow copy)를 하게된다.
즉, 내부 값이 완전히 새로 복사 되는 것이 아니라, 가장 바깥에 있는 값만 복사된다.
따라서, 내부의 값이 객체 혹은 배열이라면 내부의 값 또한 따로 복사해 주어야 한다.
다음 코드를 보면 이해가 될 것이다.

 

예시코드

const todos = [ { id: 1, checked: true }, { id: 2, checked: true }];
const nextTodos = [...todos];

nextTodos[0].checked = false;  //~> todos[0].checked === false
console.log(todos[0] === nextTodos[0]); // 아직까지 똑같은 객체를 가리키고 있어서 true

nextTodos[0] = {
  ...nextTodos[0], // { id: 1, checked: true }
  checked: false // checked 값 덮어씌움
};
console.log( todos[0] === nextTodos[0] );  // 새로운 객체를 할당해 주었기 때문에 false


만약에 객체 안에 있는 객체라면 불변성을 지키면서 새로운 값을 할당해야 하므로
다음과 같이 해야한다.


예시코드

const nextComplexObject = {
  ...complexObject,
  objectInside: {
    ...complexObject.objectInside,
    enabled: false
  }
};

console.log( complexObject === nextComplexObject ); // false
console.log( complexObject.objectInside === nextComplexObject.objectInside ); // false

 

배열 or 객체의 구조가 복잡해진다면 불변성을 유지하면서 업데이트하는 것도 까다로워진다.
이렇게 복잡한 상황일 경우 immer 라는 라이브러리를 쓰면 편하게 작업할 수 있다.

 

 

출처

리액트를 다루는 기술(11장-6) - 김민준

 

참고

1. [JS] 불변성(Immutability)

2. [React] 배열 값 추가, 제거, 수정하며 불변성 유지하기