리액트는 컴포넌트 기반 아키텍처를 따르기 때문에 각각의 컴포넌트는 다른 컴포넌트의 상태에 접근할 수 없다. 하지만 부모 - 자식 관계는 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>
);
}
이렇게 함수를 꺼내서 사용하면 불필요한 리렌더링을 막을 수 있다.
반응형
'Front end > React' 카테고리의 다른 글
React Hook 정리 (useState, useEffect) (2) | 2025.01.21 |
---|