기억의 실마리
2024. 9. 22. 21:42

🐻Zustand

Zustand가 가진 특징으로 가벼운 번들사이즈,

폭넓은 확장 가능성, provider가 없는 구조,

Flux패턴의 단방향 Pub/Sub 모델구조이다.

 

이러한 특징들로 요즘 대세 상태관리 라이브러리로

각광받고있다.

 

npm 공식 페이지에서 주간 다운로드 횟수를 보면

놀라운 주간 다운로드 횟수를 갱신중이다.

 

※ 2024-09-22 주요 상태관리 라이브러리 주간 다운로드 횟수

- Redux : 10,278,099

- Zustand : 4,243,907

- Redux-toolkit : 3,609,254

- Jotai : 1,177,983

- Recoil : 489,922

 

부동의 1위인 오리진 Redux를 제외한다면

Redux의 본체라 해도 무방한 Redux-toolkit 조차도 뛰어넘은

대세 상태관리 라이브러리이다.

 

이번 포스팅은 Zustand를 React에서 사용한다는 것을

기반으로 Zustand의 특징과 간단한 예제코드를

포스팅하고자 한다.

 

🪶가벼운 번들사이즈

Zustand는 획기적으로 가벼운 번들사이즈를 자랑한다.

고작 1.16kb의 사이즈 만으로 전체 상태를 용이하게

관리할 수 있어 프로젝트 자체의 용량을 더욱 가볍게

가져갈 수 있다.

 

🪝확장 가능성

redux와 같은 Flux패턴이기 때문에 redux의

reducer와 같은 개념으로 확장하여 유지보수성을

높일 수 있고 Zustand에서 제공하는 미들웨어를 통해

Redux dev-tools를 활용할 수 있어 디버깅에도

용이하게 확장이 가능하다.

 

🧺Provider가 없는 구조

이는 단순하게 생각하면 provider가 없어서 어쩌라고?

라는 생각이 들 수 있다. 하지만 React의 구조가 이를

엄청난 최적화요소로 만들어준다.

 

바로 Re-Render에 대한 최적화이다.

Provider로 감싸지 않는 구조로 상태 변화에 따른

불필요한 렌더링을 최소화 할 수 있게 되고

멀리보면 UX까지 영향을 끼칠 수 있는

핵심적인 요소라고 볼 수 있다.

 

📑Flux패턴의 구조

Flux패턴은 간단히 이야기 하자면 React와 Redux처럼

논리가 단방향으로 흐르는 아키텍처이며 대표적인 특징으로

디버깅이 쉽다는 특징을 가지고 있다.

 

  • Flux 패턴 시각화

사용자 입력을 기반으로 Action을 만들고 Dispatcher에

전달한 후 Store의 데이터를 변경하고 View에 반영하여

단방향의 흐름으로 작동하며, View에서 State 변경이 감지되면

순서대로 재실행한다. 이러한 흐름을 통해 누락없이

변경된 State를 반영할 수 있다.

 

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

Pub/Sub 모델은 Publish/Subscribe의 축약어로 메시지 기반의

미들웨어 시스템을 말하며, 메시지를 전송할 때 publisher(발행자)가

subscriber(구독자)에게 직접 메시지를 전송하지만 Pub/Sub 모델은

발행자(Pub)는 어떤 구독자(Sub)가 있는지 모르는 상태에서

메시지를 전송하고 구독자(Sub)발행자(Pub)에 대한 정보 없이

자신의 Interest(구독한 것)에 맞는 메시지만을 전송 받는 것을 의미한다.

 

즉, Zustand에서는 스토어의 상태 변경이 일어날 때 실행할

Listener 함수를 모아 두었다가(sub), 상태가 변경되었을 때

등록된 Listener 에게 상태가 변경되었다고 알려준다(pub).

 

🧑‍💻예제코드

간단한 예제코드로 Zustand의 미들웨어를 사용하여 Redux dev-tools를 활용가능한 코드이다.

import type {StoreApi, UseBoundStore} from "zustand";
import {create} from "zustand";
import {devtools} from "zustand/middleware";

export interface ITestObjState {
  id: number;
  title: string;
  content: string;
}

export interface ITestStore {
  testState: string;
  testObjState: ITestObjState;
  setTestState: (payload: string) => void;
  setTestObjState: (payload: ITestObjState) => void;
}

export const useTestStore: UseBoundStore<StoreApi<ITestStore>> = create(
  devtools((setState, getState, store) => ({
    testState: "default value",
    testObjState: {id: 0, title: "title", content: ""},
    setTestState: (payload: string) => setState({testState: payload}),
    setTestObjState: (payload: ITestObjState) => setState({testObjState: payload}),
  })),
);

 

위 예제코드처럼 단순하게 devtools를 감싸주기만 하면 Redux dev-tools를 활용하여 디버깅이 가능해진다.

 

✍️마치며...

기존에 Redux로 상태관리 라이브러리를 입문했지만, Zustand를 접하고 나서부터는 Redux를 거의 사용하지 않았던 것 같다. 그 만큼 DX가 좋은 라이브러리라고 생각이 들었고 대세 라이브러리로 부상한 의미를 바로 알 수 있었다. 실제로 현재 다니는 회사에서 새로 시작하게된 프로젝트에서 이전 프로젝트에서 활용하던 Redux를 그대로 채용하자고 했을 때 Zustand를 적극 추천하며 팀원을 설득한 끝에 Zustand를 본격 도입할 수 있었다. 그 이후 모두에게 확실히 편하게 써서 좋다는 말을 듣고 팀 단위에서 DX를 높인 것 같아 괜히 뿌듯했다. ㅎ