immer

taehyung·2023년 10월 17일

React.js

목록 보기
14/24

이번 포스팅에서는 리액트 불변성을 유지해주는 라이브러리인 immer에대해 적어보려 합니다.

객체나 배열의 구조가 복잡해진다면, 관리하는 상태를 업데이트하는 방법또한 복잡해지게 되는데. 이 때 immer 를 사용하면 불변성을 유지시켜줍니다.

예시

import { produce } from 'immer';

const [state, setState] = useState([
  {
    a: 'a',
    b: {
      c: 'c',
    },
  },
  {
    a: 'a',
    b: {
      c: 'c',
    },
  },
]);

위 코드의 불변성을 지켜내려면 아래와같이 스프레드 연산자를 사용해야 하는데, 구조가 복잡해지면 보기 껄끄러워집니다.

  const nextState = [
    ...state.map(
      (item) =>
        (item = {
          ...item,
          b: { ...item.b, d: 'd 추가' },
        }),
    ),
  ];

immer를 사용하면 불변성을 신경쓰지 않아도 괜찮습니다.

 const nextState2 = produce(state, (draft) => {
    draft.map((item) => (item.b.d = 'd추가'));
  });

아래는 벨로퍼트 님의 글을사용 했습니다.
출처 : https://react.vlpt.us/basic/23-immer.html

Immer 은 분명히 정말 편한 라이브러리인것은 사실입니다. 하지만, 확실히 알아둘 점은, 성능적으로는 Immer 를 사용하지 않은 코드가 조금 더 빠르다는 점 입니다.

위 성능 분석표는 50,000개의 원소중에서 5,000 개의 원소를 업데이트 하는 코드를 비교 했을때의 결과입니다. 보시면, Immer 의 경우 31ms 걸리는 작업이 (map 을 사용하는) Native Reducer 에서는 6ms 걸린 것을 확인 할 수 있습니다.

그런데, 이렇게 데이터가 많은데도 31ms 가 걸린다는 것은 사실 큰 문제가 아닙니다. 인간이 시각적으로 인지 할 수있는 최소 딜레이는 13ms 라고 합니다 (참고]) 그런 것을 생각하면 25ms 의 차이는, 사실 그렇게 큰 차이가 아니기 때문에 걱정할 필요 없습니다. 심지어, 데이터가 50,000개 가량 있는게 아니라면 별로 성능 차이가 별로 없을 것이기 때문에 더더욱 걱정하지 않아도 됩니다.

단, Immer 는 JavaScript 엔진의 Proxy 라는 기능을 사용하는데, 구형 브라우저 및 react-native 같은 환경에서는 지원되지 않으므로 (Proxy 처럼 작동하지만 Proxy는 아닌) ES5 fallback 을 사용하게 됩니다. ES5 fallback 을 사용하게 되는경우는 191ms 정도로, 꽤나 느려지게 됩니다. 물론, 여전히 데이터가 별로 없다면 크게 걱정 할 필요는 없습니다.

Immer 라이브러리는 확실히 편하기 때문에, 데이터의 구조가 복잡해져서 불변성을 유지하면서 업데이트하려면 코드가 복잡해지는 상황이 온다면, 이를 사용하는 것을 권장드립니다.

다만, 무조건 사용을 하진 마시고, 가능하면 데이터의 구조가 복잡해지게 되는 것을 방지하세요. 그리고 어쩔 수 없을 때 Immer 를 사용하는것이 좋습니다. Immer 를 사용한다고 해도, 필요한곳에만 쓰고, 간단히 처리 될 수 있는 곳에서는 그냥 일반 JavaScript 로 구현하시길 바랍니다.

profile
Front End

0개의 댓글