일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Login
- @Entity
- Polylang
- set
- @Repository
- db
- @Controller
- 데이터베이스
- router
- post
- 리액트오류
- 구글애널리틱스
- 구글
- 플러그인
- JPA
- 구글알고리즘
- GA4
- HttpSession
- ussstate
- ChatGPT
- Thymeleaf
- 워드프레스
- GET
- @Query
- 인텔리제이
- SEO
- firebase
- useEffect
- useContext
- linkedhastset
- Today
- Total
개발천재
[ReactJS] 상태 관리를 더 쉽게, Zustand 본문
Zustand란?
Zustand는 React에서 상태(state)를 쉽게 관리할 수 있게 해주는 도구(라이브러리)이다.
React에서는 일반적으로 useState나 useContext를 쓰는데, 컴포넌트가 많아지면 상태를 공유하거나 관리하는 게 점점 복잡해진다. Zustand는 공용 창고처럼 이걸 한 곳에 다 모아서 관리하게 해주는 역할을 한다. 컴포넌트 간 상태 공유가 필요할 때, 또는 상태를 한 곳에 깔끔히 모아두고 싶을 때 유용하게 쓰인다.
Zustand 사용 목적
React에서 버튼 컴포넌트에서 숫자를 올렸는데, 헤더, 사이드바, 푸터에도 그 숫자가 보여야 하는 경우가 있다. 이럴 땐 상태를 여러 컴포넌트끼리 공유해야 한다. Zustand는 이런 걸 아주 간단하게 만들어준다.
Zustand가 항상 필요한 건 아니다. 예를 들어 컴포넌트 하나 안에서만 쓰는 count, toggle, input 같은 단순 상태는 그냥 useState로 충분하다. 프로젝트 규모가 작고, 상태 공유가 거의 없을 땐 Zustand를 쓰지 않아도 된다.
1) 여러 컴포넌트에서 같은 상태를 써야 할 때
예: 로그인 사용자 정보 (user)
로그인하면 유저 이름, 프로필, 토큰 같은 정보를 저장해야한다. 이 정보는 헤더, 사이드바, 마이페이지, 설정 페이지 등 여기저기에서 사용된다. 만약 이런 상태를 매번 props로 넘기거나 useContext로 관리하면 번거롭고 복잡하다. 그러나 Zustand로 한 번에 공유하면 코드가 깔끔해진다.
// store.js
import { create } from 'zustand'
const useUserStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
logout: () => set({ user: null }),
}))
export default useUserStore
// Header.jsx
import useUserStore from './store'
function Header() {
const user = useUserStore((state) => state.user)
return <div>{user ? `안녕하세요, ${user.name}` : '로그인 해주세요'}</div>
}
// Login.jsx
import useUserStore from './store'
function Login() {
const setUser = useUserStore((state) => state.setUser)
const handleLogin = () => {
const fakeUser = { name: '홍길동', email: 'hong@test.com' }
setUser(fakeUser)
}
return <button onClick={handleLogin}>로그인</button>
}
2) 페이지가 바뀌어도 상태를 유지하고 싶을 때
예: 장바구니
예를 들어 사용자가 쇼핑몰에서 물건을 담았다고 가정해보자. 페이지를 여기저기 옮겨 다녀도 장바구니에 담긴 정보는 유지되어야 한다. useState는 컴포넌트가 사라지면 날아가지만 Zustand는 전역에 저장하기 때문에 날아갈 문제가 없다.
// cartStore.js
import { create } from 'zustand'
const useCartStore = create((set) => ({
cart: [],
addToCart: (item) => set((state) => ({ cart: [...state.cart, item] })),
removeFromCart: (id) => set((state) => ({
cart: state.cart.filter(item => item.id !== id)
})),
}))
// ProductPage.jsx
import useCartStore from './cartStore'
function Product({ product }) {
const addToCart = useCartStore((state) => state.addToCart)
return <button onClick={() => addToCart(product)}>장바구니 담기</button>
}
// CartPage.jsx
import useCartStore from './cartStore'
function CartPage() {
const cart = useCartStore((state) => state.cart)
return (
<ul>
{cart.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
)
}
3) 모달, 토스트 등 UI 상태를 전역에서 제어할 때
예: 토스트 메시지
에러 나면 어느 컴포넌트에서든 showToast("에러 발생") 를 나타나게 하고 싶다. 그런데 useState는 특정 컴포넌트 안에 있어야 한다. Zustand를 쓰면 showToast 함수를 전역으로 두고, 어디서든 실행할 수 있다.
// uiStore.js
import { create } from 'zustand'
const useUIStore = create((set) => ({
toastMessage: '',
showToast: (msg) => set({ toastMessage: msg }),
clearToast: () => set({ toastMessage: '' }),
}))
export default useUIStore
// Anywhere.jsx(에러 발생 시)
import useUIStore from './uiStore'
function SomeComponent() {
const showToast = useUIStore((state) => state.showToast)
return (
<button onClick={() => showToast('에러가 발생했어요!')}>
오류 발생 버튼
</button>
)
}
// Toast.jsx
import useUIStore from './uiStore'
function Toast() {
const { toastMessage, clearToast } = useUIStore()
if (!toastMessage) return null
return (
<div onClick={clearToast} className="toast">
{toastMessage}
</div>
)
}
4) 게임, 시뮬레이션, 실시간 앱 등 상태가 자주 바뀌는 앱
예: 클릭 게임 점수, 물리 시뮬레이션 등
상태가 0.1초마다 막 바뀌고, 복잡한 구조를 갖고 있는 앱에서는 복잡한 상태 관리보단 간단하고 빠르게 쓸 수 있는 도구가 필요하다. Zustand는 가볍고 빠르기 때문에 이런 앱에서도 잘 사용할 수 있다.
// gameStore.js
import { create } from 'zustand'
const useGameStore = create((set) => ({
score: 0,
increase: () => set((state) => ({ score: state.score + 1 })),
reset: () => set({ score: 0 }),
}))
export default useGameStore
// Game.jsx
import useGameStore from './gameStore'
function Game() {
const { score, increase, reset } = useGameStore()
return (
<div>
<h1>점수: {score}</h1>
<button onClick={increase}>+1</button>
<button onClick={reset}>초기화</button>
</div>
)
}
5) 폼 데이터를 여러 페이지에 걸쳐서 저장할 때 (멀티스텝 폼)
예: 회원가입 단계
예를 들어 회원가입을 하는데 먼저 이름을 입력하는 페이지가 나오고, 다음에 주소를 입력하는 페이지가 나오고, 여러 페이지에 걸쳐서 폼이 나온다고 가정해보자. 이렇게 하면 각 단계마다 입력한 내용을 다음 페이지에서도 기억하고 있어야 한다. 이런 경우 상태를 하나로 묶어 Zustand에 저장하면 깔끔하게 처리할 수 있다.
// formStore.js
import { create } from 'zustand'
const useFormStore = create((set) => ({
form: {
name: '',
email: '',
password: ''
},
updateForm: (newValues) =>
set((state) => ({ form: { ...state.form, ...newValues } })),
}))
export default useFormStore
// Step1.jsx
import useFormStore from './formStore'
function Step1() {
const { form, updateForm } = useFormStore()
return (
<input
value={form.name}
onChange={(e) => updateForm({ name: e.target.value })}
placeholder="이름 입력"
/>
)
}
// Step2.jsx
import useFormStore from './formStore'
function Step2() {
const { form, updateForm } = useFormStore()
return (
<input
value={form.email}
onChange={(e) => updateForm({ email: e.target.value })}
placeholder="이메일 입력"
/>
)
}
사용방법
Zustand 설치하기
터미널에 아래의 코드를 입력하여 Zustand 설치를 진행한다.
npm install zustand
상태 만들기
store.js 파일에 상태(state)를 만든다.
아래의 코드는 상태 count와 증가/감소 함수 increase, decrease를 만든 예제이다.
// store.js
import { create } from 'zustand'
const useStore = create((set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
decrease: () => set((state) => ({ count: state.count - 1 })),
}))
컴포넌트에서 사용하기
이 Counter 컴포넌트에서는 어디서든 count 값을 가져다 쓸 수 있다. 다른 컴포넌트에서도 마찬가지이다.
// Counter.js
import React from 'react'
import useStore from './store'
function Counter() {
const count = useStore((state) => state.count)
const increase = useStore((state) => state.increase)
const decrease = useStore((state) => state.decrease)
return (
<div>
<h1>{count}</h1>
<button onClick={decrease}>-</button>
<button onClick={increase}>+</button>
</div>
)
}
요약 정리
- create() : 상태를 만드는 함수
- useStore : 만든 상태를 가져오는 Hook
- set() : 상태를 변경하는 함수
- state : 현재 상태 값
'개발 준비 > ReactJS' 카테고리의 다른 글
[ReactJS] 원자 단위로 상태 관리하기, Jotai (0) | 2025.04.30 |
---|---|
[ReactJS] 데이터 공유를 위한 useContext 알아보기 (0) | 2025.04.04 |
[ReactJS] Nested Route 중첩 라우팅 (0) | 2025.02.06 |
[ReactJS] 컴포넌트(Component) 이해하기, 만들기 (0) | 2025.02.06 |
[ReactJS] Props 이해하기, 사용하기 (0) | 2025.02.05 |