[패스트캠퍼스 수강 후기] 프론트엔드 인강 100% 환급 챌린지 29회차 미션 - 30강 Immer

1 minute read

Immer

한 객체에 값을 직접 수정하는 코드는 불변성을 깨트리는 행위다. 그래서 이전에 ‘…‘이렇게 스프레드 형식으로 값을 옮겨쓰며 새로운 상태를 만들어줬었다. 배열도 마찬가지로 concat이나 filter를 사용하여 새로운 배열을 만들어서 수정을 해줬다. 하지만 만약에 상태가 복잡해지면 불변성을 지켜가면서 새로운 상태를 만들어내는게 복잡해진다. **이럴땐 Immer를 사용하게되면 draft를 통해서 불변성을 해치는 코드를 작성해도 대신 불변성을 유지해준다. **
우선 Immer를 설치해보자. 터미널에서 아래와 같이 입력한다.

yarn add immer

라이브러리가 자동으로 설치된다. 이제 App컴포넌트 상단에서 immer를 불러와준다.

import produce from 'immer'; //produce대신에 immer를 써줄수도 있다.

produce를 나중에 우리가 만든 reducer에서 사용해줄 것이다. draft를 사용하면 기존의 객체는 그대로 두면서 새로 객체를 복사하면서 변경될 값을 업데이트 해준다. 간단하게 쓰는 방법을 설명하면 아래와 같다.

const array = [
  {id: 1, text: 'a'},
  {id: 2, text: 'b'},
  {id: 3, text: 'c'}
]; // 이런 배열에 immer로 상태를 추가하려면?
const nextArray = produce(array, draft => {
  draft.push({ id: 4, text: 'd'}); //배열안에 추가
  draft[0].text = draft[0].text + 'aaa'; //배열 내부의 수정
});

이렇게 써줄 수 있다. nextArray를 찍어보면 업데이트 된 배열이 나오고, 기존 array를 찍어보면 이전과 똑같이 유지되는 것을 볼 수 있다.
그럼 기존에 만들었던 App컴포넌트에서 reducer함수를 위와 같은 식으로 고쳐보자.

function reducer(state, action){
  switch (action.type){
    case 'CREATE_USER':
      return produce(state, draft => {
        draft.users.push(action.user);
      })
      // return {
      //   inputs: initialState.inputs,
      //   users: state.users.concat(action.user)
      // }
    case 'TOGGLE_USER':
      return produce(state, draft => {
        const user = draft.users.find(user => user.id === action.id);
        user.active = !user.active;
      })
      // return {
      //   ...state,
      //   users: state.users.map(user =>
      //     user.id === action.id
      //     ? { ...user, active: !user.active }
      //     : user
      //     )
      // };
    case 'REMOVE_USER':
      return produce(state, draft => { //splice로 지워줌
        const index = draft.users.findIndex(user => user.id === action.id);
        draft.users.splice(index, 1);
      });
      // return {
      //   ...state,
      //   users: state.users.filter(user => user.id !== action.id)
      // }
    default:
      throw new Error('Unhandled action');
  }
}

주석처리한 부분이 이전 코드고, 새로 쓴 것이 immer를 사용한 코드다. TOGGLE_USER 같은 경우는 immer가 깔끔하지만, 나머지 CREATE_USER나 REMOVE_USER는 기존코드가 더 깔끔해보인다. 업데이트 로직이 까다로울 경우에만 immer를 사용해도된다. 어차피 필수 라이브러리는 아니기때문에 원할경우만 사용하면 된다. immer속도 그리고 단점이 하나 있는데 immer는 proxy처럼 작동하기 때문에 구형브라우저나 구형 react native에서는 돌아가지 않는다. (react native 최신버전은 돌아간다고 함) 그리고 사실상 속도면에서 있어서 javascript만으로 된 코드보다는 약간의 속도가 걸린다. (오만개의 데이터가 있다고 가정했을때 34밀리세컨드 정도, 사용자가 체감할만한 속도까진 아님) 이런 단점이 있긴 하지만 코드가 심각하게 복잡한 곳에서는 immer로 구현해보도록 하자.

오늘은 여기까지..
시청 영상 30강 26~27까지

수강인증이미지
수강인증이미지

프론트엔드 개발 올인원 패키지 with React Online. 👉 https://bit.ly/31Cf1hp

Comments