이 글에서는 Zustand와 TypeScript를 활용해 서비스의 리스트들의 데이터를 관리하는 ListStore를 구현하는 과정을 공유합니다.
Zustand란?
Zustand는 React 기반의 상태 관리 라이브러리로, 가볍고 간단한 API를 제공합니다. 기존의 상태 관리 라이브러리인 Redux와 비교했을 때 설정이 간소화되어 있고, 직관적인 코드 작성을 가능하게 합니다.
1. Zustand로 리스트 상태 관리 스토어 구현하기
초기 상태 정의하기
리스트 상태를 관리하기 위해 listInitialState를 정의합니다. 이 객체는 다양한 리스트 데이터를 초기화합니다.
const listInitialState = {
...allLists,
};
export type ListState = typeof listInitialState;
allLists는 리스트별 데이터를 관리하는 기본 상태로, 이를 확장하여 사용합니다.
2. 액션 함수 정의하기
액션들의 관리를 용이하게 하기 위하여 스토어에 추가되는 액션을 따로 분리하고, 하나의 setAction으로 동작하도록 처리하였습니다.
const actions = (setState: StoreApi<ListState>["setState"]) => {
const setStateAction = (name: string, key: string, value: unknown) => {
setState((state) => {
const stateSlice = state[name as keyof ListState] as Record<string, unknown>;
stateSlice[key] = value;
return { ...state };
});
};
return {
setListPage: (name: string, current_page: number, per_page: number) => {
setStateAction(name, "current_page", current_page);
setStateAction(name, "per_page", per_page);
},
setSearchParam: (name: string, searchParam?: unknown) => {
setStateAction(
name,
"searchParam",
searchParam ?? initSearchParam[name as keyof InitSearchParam],
);
},
};
};
- setListPage: 현재 페이지(current_page)와 페이지 당 데이터 수(per_page)를 설정합니다.
- setSearchParam: 리스트의 검색 파라미터를 설정합니다. 기본값으로 initSearchParam 객체를 참조합니다.
3. 스토어 생성하기
Zustand의 create 함수와 미들웨어(devtools, combine)를 활용해 스토어를 생성합니다.
export const listStore = create(
devtools(combine(listInitialState, actions), { name: "listStore" }),
);
- combine: 초기 상태와 액션을 결합합니다.
- devtools: 브라우저 개발자 도구에서 상태 변화를 쉽게 디버깅할 수 있도록 합니다.
4. 타입 선언하기
스토어의 타입을 명시하여 안전성을 강화합니다.
export type ListStore = typeof listStore;
5. 최종 코드
아래는 위 내용을 종합한 최종 코드입니다:
import type { StoreApi } from "zustand";
import { create } from "zustand";
import { combine, devtools } from "zustand/middleware";
import type { InitSearchParam } from "@src/store/initialization/list";
import { allLists, initSearchParam } from "@src/store/initialization/list";
const listInitialState = {
...allLists,
};
export type ListState = typeof listInitialState;
const actions = (setState: StoreApi<ListState>["setState"]) => {
const setStateAction = (name: string, key: string, value: unknown) => {
setState((state) => {
const stateSlice = state[name as keyof ListState] as Record<string, unknown>;
stateSlice[key] = value;
return { ...state };
});
};
return {
setListPage: (name: string, current_page: number, per_page: number) => {
setStateAction(name, "current_page", current_page);
setStateAction(name, "per_page", per_page);
},
setSearchParam: (name: string, searchParam?: unknown) => {
setStateAction(
name,
"searchParam",
searchParam ?? initSearchParam[name as keyof InitSearchParam],
);
},
};
};
export const listStore = create(
devtools(combine(listInitialState, actions), { name: "listStore" }),
);
export type ListStore = typeof listStore;
마무리
이 글에서는 Zustand를 활용해 리스트 데이터를 관리하는 스토어를 구현하는 방법을 살펴봤습니다. 상태관리를 구현하는 다양한 방법이 있겠지만 점점 사용자가 늘어나는 Zustand 사용하여 상태관리를 구현해보면 어떤식이 될 것인가에 대해서 정리해 보았습니다.