Zustand- with Immer 적용하기

·2024년 11월 1일
0

개발 관련 

목록 보기
4/4

Zustand와 Emotion을 활용하여 간단한 투두리스트를 구현하던 중, 할 일 체크 기능을 구현하는 과정에서 Immer를 활용해봤다.

todo
디자인은 일단 뒷전...

현재 ZUSTAND에서 체크 상태관리 함수


// checkTodo 예시
checkTodo: (id) =>
  set((state) => ({
    todo_list: state.todo_list.map((todo) =>
      todo.id === id ? { ...todo, isChecked: !todo.isChecked } : todo
    ),
  })),

이렇게 일일히 map 돌면서 id를 찾고, 거기에 이제 스프레드연산자 활용해서 체크기능 구현했는데, 코드가 너무 번잡하게 느껴짐

  • 좀 복잡한 것 같아서, 이런식으로 구현하는게 맞나? 하는 마음으로 공식페이지를 보니
공식문서


1. Immer
2. optics-ts
3. Ramda

이렇게 복잡한 구조에 대한 솔루션을 3가지 추천하고 있었.
그 중 그나마 들어봤고, 간단해보이는 Immer에 대해서 알아봤다.

💡 Immer.js란?

  • react에서 불변성을 유지하는 코드를 작성하기 쉽게 해주는 라이브러리

상태를 변경하는데 불변성을 유지하는 코드?라는것은 이게 바꾸고자하는 상태를 제외한 모든 상태를 바뀌지않게 묶어두면서 변경하는 코드 라는 뜻을 의미하는 듯 하다

가장 큰 장점은 가독성이 올라간다고 한다.

공식문서의 극단적인 예시를 보면 deep.nested.obj..

normalInc: () =>
    set((state) => ({
      deep: {
        ...state.deep,
        nested: {
          ...state.deep.nested,
          obj: {
            ...state.deep.nested.obj,
            count: state.deep.nested.obj.count + 1
          }
        }
      }
    }))
  • 이전: spread 연산자(...)를 사용하여 불변성을 유지하는데, 이걸 일일히 파고 들어가니까 코드가 길어지고 번잡해진다.
  • IMMER 사용 이후
immerInc: () =>
    set(produce((state: State) => { ++state.deep.nested.obj.count })),

이렇게 코드길이와 가독성 면에서 더 눈에 띄는 개선이 이루어진 것을 확인할 수 있다.

//1안 -> Without Immer
const onToggle = id => {
  setUsers(
    users.map(user =>
      user.id === id ? { ...user, active: !user.active } : user
    )
  );
};

//2안 -> With Immer
setState(state => {...state, key: newValue})

딱봐도 알 수 있듯이 한눈에도 코드가 줄은 것이 확인이 가능했다. 약간 lodash처럼 좀 더 쉽게 원하는 기능을 구성하게끔 메소드를 제공하는 라이브러리 정도라고 이해할 수 있었다.

그래서 이제 내 코드에 적용을 하자면…

이전 코드 vs Immer 적용 코드

이전 코드

checkTodo: (id) =>
  set((state) => ({
    todo_list: state.todo_list.map((todo) =>
      todo.id === id ? { ...todo, isChecked: !todo.isChecked } : todo
    ),
  })),

Immer 적용 코드

checkTodo: (id) => set(
  produce((state) => {
    const todo = state.todo_list.find(todo => todo.id === id);
    if (todo) {
      todo.isChecked = !todo.isChecked;
    }
  })
),

주의사항

  • 단순한 상태 업데이트(예: setNewTodo)의 경우 Immer를 사용할 필요 없음
  • Immer는 약간의 성능 오버헤드가 있을 수 있으므로, 매우 간단한 상태 업데이트에는 불필요할 수 있음

지금은 depth가 한단계 뿐이 없어서 사실 map을 돌려도 큰 문제는 없는데, 이후에 더 깊은 상태관리에서는 코드의 안정성이나 가독성이 너무 좋은 것 같아서 자주 사용할 예정이다.

profile
기억보단 기록을

0개의 댓글