Zustand 한 방에 정리

장유진·2022년 10월 13일
5

공식문서: https://github.com/pmndrs/zustand

기본 사용법

1. Store 선언

import create from 'zustand';

// set method로 상태 변경 가능
const useStore = create(set => ({
  count: 0,
  increaseCount: () => set(state => ({ count: state.count + 1 })),
  setThree: (input) => set({ count: input }),
}));

2. Store 사용

function App() {
  const { count, increaseCount, setThree } = useStore();
  return (
    <div className='App'>
      <div>Zustand ! {count}</div>
      <button onClick={increaseCount}>+1</button>
      <button onClick={() => setNum(3)}>set3</button>
    </div>
  );
}

3. devtools를 사용하여 디버깅하기

Redux devtools를 크롬 웹 스토어에서 설치해준 후, 아래처럼 store와 devtools를 연결해준다.
애플리케이션을 브라우저로 띄우고 개발자도구 창에서 Redux devtools를 확인하면 store의 상태를 확인할 수 있다.

import create from 'zustand'
import { devtools } from 'zustand/middleware'

const store = (set) => ({
  bears: 0,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 })
})

const useStore = create(devtools(store))

export default useStore

4. production일 때와 development일 때 분기처리

분기처리를 사용하여 development일 때만 devtools를 사용하여 디버깅 할 수 있다.

import create from 'zustand'
import { devtools } from 'zustand/middleware'

const store = (set) => ({
  bears: 0,
  increasePopulation: () => set(state => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 })
})

const useStore = create(
  process.env.NODE_ENV !== 'production' ? devtools(store) : store
)

export default useStore

다른 상태관리 라이브러리와 비교

zustand vs jotai

zustand는 jotai를 만든 사람이 만들었다고 한다. 왜지..?
암튼 이 둘을 비교한 글 => https://github.com/pmndrs/jotai/issues/13

jotai vs recoil vs zustand

npm trend: https://npmtrends.com/jotai-vs-recoil-vs-zustand

recoil

  • javascript로 작성
  • bottom-up 방식 : atom 단위로 상태관리
  • 최소 단위 Atom을 만들기 위해 key가 필요함
  • provider 필요

jotai

  • typescript로 작성
  • recoil에 영향을 받아 만들어짐
  • bottom-up 방식 : atom 단위로 상태관리
  • Atom key가 필요없음(코드가 미세하게 줄어듬)
  • 리액트 state 함수인 useState 와 유사한 인터페이스
  • provider 일반적으로 필요

zustand

  • typescript로 작성
  • 리덕스를 축소화시킨 느낌으로 리덕스와 유사함
  • 스토어 형태
  • provider 필요없음 -> 앱을 래핑하지 않아도 되기 때문에 불필요한 리렌더링 최소화

Zustand 장점

  • 굉장히 쉽다. 동작을 이해하기 위해 알아야 하는 코드 양이 아주 적다. 핵심 로직의 코드 줄 수가 약 42줄밖에 되지 않는다. (VanillaJS 기준)
  • 보일러플레이트가 거의 없다. (Context API랑 비교)
  • redux Devtools를 사용할 수 있어 debugging에 용이하다.
  • 상태 변경 시 불필요한 리랜더링을 일으키지 않도록 제어하기 쉽다.
  • 특정 라이브러리에 엮이지 않는다. (그래도 React와 함께 쓸 수 있는 API는 기본적으로 제공한다.)
  • 한 개의 중앙에 집중된 형식의 스토어 구조를 활용하면서, 상태를 정의하고 사용하는 방법이 단순하다.
  • Context API를 사용할 때와 달리 상태 변경 시 불필요한 리랜더링을 일으키지 않도록 제어하기 쉽다.
  • React에 직접적으로 의존하지 않기 때문에 자주 바뀌는 상태를 직접 제어할 수 있는 방법도 제공한다.
  • 동작을 이해하기 위해 알아야 하는 코드 양이 아주 적다. 핵심 로직의 코드 줄 수가 약 42줄밖에 되지 않는다. (VanillaJS 기준)

동작원리

Flux 패턴

zustand는 MVC 패턴이 아닌 Flux 패턴을 사용한다.
Flux 패턴란 사용자 입력을 기반으로 Action을 만들고 Action을 Dispatcher에 전달하여 Store(Model)의 데이터를 변경한 뒤 View에 반영하는 단방향의 흐름으로 애플리케이션을 만드는 아키텍처이다.
각 요소들은 단방향 흐름에 따라 순서대로 역할을 수행하고, View로부터 새로운 데이터 변경이 생기면 처음부터 다시 이 순서대로 실행한다. 이렇게 함으로써 예외 없이 데이터를 처리할 수 있게 된다.

Sub/Pub (발행/구독) 모델

zustand는 Sub/Pub 모델을 기반으로 이루어져있다.
스토어의 상태 변경이 일어날 때 실행할 Listener를 모아두었다가(Sub) 상태가 변경되었을때 등록된 Listener들에게 상태가 변경되었다고 알려준다(Pub).

클로저

zustand는 스토어를 생성하는 함수를 호출할 때 클로저를 활용한다. 클로저는 간단히 말해 '함수가 선언될 시 그 주변 환경을 기억하는 것'으로, 스토어의 상태는 스토어를 조회하거나 변경하는 함수 바깥 스코프에 항상 유지되도록 만들어져있다. 그러면 상태의 변경, 조회, 구독 등의 인터페이스를 통해서만 스토어를 다루고 실제 상태는 애플리케이션의 생명 주기 처음부터 끝까지 의도치 않게 변경되는 것을 막을 수 있다.

Zustand 코어 코드 분석

https://ui.toast.com/weekly-pick/ko_20210812

코어 코드 분석은 너무 양이 많고 어려워서 정리하지 못했다. 하지만 위의 글에 잘 설명되어있으니 읽어볼 것!


Reference

profile
프론트엔드 개발자

0개의 댓글