ReactJS
React - Zustand
jjangsh
2024. 9. 25. 00:47
01. Zustand의 등장배경
(1) 상태관리의 중요성
상태관리는 모든 리액트 애플리케이션에서 매우 중요합니다. 작은 규모의 애플리케이션에서는 상태관리가 간단하지만, 애플리케이션이 커질수록 상태관리는 점점 더 복잡해집니다.
상태(state)는 리액트 애플리케이션에서 데이터와 UI의 현재 상태를 나타냅니다. 상태가 변경되면 UI도 업데이트되어야 합니다.
(2) Zustand의 필요성
기존의 상태관리 라이브러리인 Redux는 제공하는 기능과 연계된 미들웨어 등 매우 강력한 퍼포먼스를 자랑하지만, 설정과 사용법이 복잡했죠! Zustand는 상태관리 본연의 기능에 집중하여 위와 같은 복잡성을 줄이고, 보다 간단하고 직관적인 상태관리 기능을 제공합니다.
02. Zustand의 주요 개념
(1) Zustand의 주요 특징
- 간결함
- 매우 간단한 API를 제공하기 때문에, 학습 곡선이 완만해요.
- 매우 적은 설정 코드 및 적용 코드를 이용하여 상태관리 기능을 구현할 수 있어요.
- 성능
- 불필요한 리렌더링을 방지하는 등, 성능 최적화가 잘 되어 있습니다.
- Zustand는 상태가 변경될 때, 해당 상태를 사용하고 있는 컴포넌트만 리렌더링 해요.
- 상태의 일부가 변경되었을 때 그 상태를 사용하는 컴포넌트만 업데이트되므로, 애플리케이션 전체가 리렌더링 되지 않습니다. 이를 통해 성능을 최적화하고, 리렌더링으로 인한 성능 저하를 방지할 수 있습니다.
- React와의 통합
- React의 훅(Hook)과 완벽하게 통합됩니다.
- Zustand는 React의 useState, useEffect와 같은 기본 훅을 사용하는 것처럼 간편하게 사용할 수 있어요.
(2) 설치 및 기본 사용법
Zustand 설치
yarn add zustand
기본 사용법
// src > zustand > bearsStore.js
import { create } from "zustand";
const useBearsStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}));
export default useBearsStore;
// src > App.jsx
import "./App.css";
import useBearsStore from "./zustand/bearsStore";
function App() {
const bears = useBearsStore((state) => state.bears);
const increasePopulation = useBearsStore((state) => state.increasePopulation);
return (
<div>
<h1>{bears} around here ...</h1>
<button onClick={increasePopulation}>one up</button>
</div>
);
}
export default App;
03. Zustand와 Redux Toolkit 비교
(1) 설정 및 사용법 비교
Zustand: 매우 간단한 설정과 사용법을 제공해요! 우리가 이미 경험해 본 대로 상태를 정의하고 사용하는 과정이 직관적이에요.
import { create } from "zustand";
const useStore = create(set => ({
bears: 0,
increasePopulation: () => set(state => ({ bears: state.bears + 1 }))
}))
Redux Toolkit: 보다 구조화된 방법을 제공하지만, 설정이 다소 복잡할 수 있어요. 보일러 플레이트가 너무 많다 보니 상태 하나를 관리하고자 해도 추가/설정해야 하는 것이 상당합니다.
import { configureStore, createSlice } from '@reduxjs/toolkit'
const slice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: state => { state.value += 1 }
}
})
const store = configureStore({ reducer: slice.reducer })
(2) 장단점 비교
- Zustand
- 장점: 간단하고 빠르며, 설정이 매우 쉽습니다.
- 단점: 상태가 커지면 관리가 어려울 수 있습니다.
- Redux Toolkit
- 장점: 구조화된 방법을 통해 대규모 애플리케이션에서도 관리가 용이합니다.
- 단점: 설정이 복잡하고, 학습 곡선이 가파릅니다.
04. 예시코드
(1) 기본 예제
(1)-1. 상태 정의
// src > zustand > todosStore.js
import { create } from "zustand";
const useTodosStore = create(set => ({
todos: [],
addTodo: (todo) => set(state => ({ todos: [...state.todos, todo] })),
removeTodo: (index) => set(state => ({
todos: state.todos.filter((_, i) => i !== index)
}))
}))
export default useTodosStore;
(1)-2. 상태 사용
// src > App.jsx
import React, { useState } from "react";
import useTodosStore from "./zustand/todosStore";
function App() {
const todos = useTodosStore((state) => state.todos);
const addTodo = useTodosStore((state) => state.addTodo);
const removeTodo = useTodosStore((state) => state.removeTodo);
const [input, setInput] = useState("");
return (
<div>
<h1>Todo List</h1>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button
onClick={() => {
addTodo(input);
setInput("");
}}
>
Add Todo
</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>
{todo} <button onClick={() => removeTodo(index)}>Remove</button>
</li>
))}
</ul>
</div>
);
}
export default App;
05. Zustand의 장점과 단점
(1) 장점
- 간편한 사용: 간단한 API와 직관적인 사용법을 제공합니다.
- 성능 최적화: 불필요한 리렌더링을 방지합니다.
- React와의 완벽한 통합: React의 훅과 잘 통합되어 있습니다.
- 미들웨어 지원: 로깅, 퍼시스턴스 등 다양한 미들웨어를 사용할 수 있습니다.
- 유연성: 필요한 부분만 선택적으로 사용할 수 있습니다.
- 커뮤니티와 자료: 예전엔 다른 대형 라이브러리에 비해 상대적으로 커뮤니티와 자료가 부족할 수 있었지만 꾸준한 인기 상승으로 많은 자료가 확보되고 있습니다.
(2) 단점
- 상태가 커지면 관리 어려움: 상태가 많아지면 관리가 복잡해질 수 있습니다.
(3) Redux Toolkit과의 비교
- 설정과 사용법: Zustand는 설정과 사용이 간단하며, Redux Toolkit은 더 구조화된 방법을 제공합니다.
- 성능: 두 라이브러리 모두 성능 최적화가 잘 되어 있지만, Zustand는 불필요한 리렌더링을 방지하는 데 더 초점을 맞춥니다.
- 유연성: Zustand는 필요한 부분만 선택적으로 사용할 수 있지만, Redux Toolkit은 보다 강력한 구조화된 방법을 제공합니다.
- 커뮤니티와 자료: Redux Toolkit은 대형 커뮤니티와 풍부한 자료를 가지고 있으며, Zustand는 상대적으로 부족할 수 있지만 현재는 많은 인기에 힘입어 늘어나고 있습니다.