Front end/React

[상태관리] Zustand란?

re-hwi 2025. 2. 24. 00:14

리액트는 컴포넌트 기반 아키텍처를 따르기 때문에 각각의 컴포넌트는 다른 컴포넌트의 상태에 접근할 수 없다. 하지만 부모 - 자식 관계는 props를 통해 상태를 전달할 수 있다. 리액트는 "단방향 데이터 흐름" 을 따르기 때문에 부모에서 자식으로 데이터 전달이 가능하지만, 자식에서 부모로 데이터 전달은 불가능하다.

사실 부모에서 콜백함수를 전달한다던지, 상태를 끌어올리는 방법을 통해 어느 정도 구현이 가능하지만 이 또한 컴포넌트가 많아진다면 드릴링의 문제가 생길 수 있다.

그래서 상태관리 라이브러리가 탄생했다. 상태관리 라이브러리는 전역의 저장소에서 상태를 관리할 수 있도록 돕는다. 이 저장소는 어느 컴포넌트에서도 접근 및 제어가 가능하다.

그 중 대표적인 라이브러리가 바로 zustand와 redux이다. 그 중 zustand는 가볍고 간결한 문법을 가지고 있어 작은 프로젝트에 사용하기 적합하다.

Zustand 시작하기

패키지 설치

pnpm add zustand    # npm i zustand

zustand를 사용하기 위해 프로젝트에 패키지를 설치한다.

스토어 생성

import { create } from 'zustand';

export const useStore = create()

이렇게 creat라는 함수를 가져와 사용하면 useStore라는 저장소 훅을 만들 수 있다.

데이터 및 함수 생성

스토어를 만들었으니 전역으로 관리 될 데이터를 정의해야 한다. 그리고 그 데이터를 조작할 함수도 스토에 내부에 정의한다.

const useStore = create((set) => ({
  count: 0, // count 상태의 초기값
  increment: () => set((state) => ({ count: state.count + 1 })), // increment(증가) 함수 정의
  decrement: () => set((state) => ({ count: state.count - 1 })), // decrement(감소) 함수 정의
  update: (value) => set(() => ({count: value}))
}));

필요한 컴포넌트에서 스토어 사용

데이터 꺼내오기

import { useStore } from '@/stores/count';

function CountDisplay() {
  const count = useStore((state) => state.count);

  return (
    <output>{count}</output>
  );
}

함수 꺼내오기

import { useStore } from '@/stores/count';

function CountControls() {
  const [update, increment] = useStore(
      (state) => [state.update, state.increment]
    );

  return (
    <div role="group" className="flex gap-1">
      <button type="button" onClick={increment}>+1</button>
      <button type="button" onClick={() => update(99)}>99</button>
    </div>
  );
}

이렇게 함수를 꺼내서 사용하면 불필요한 리렌더링을 막을 수 있다.

반응형