프로젝트 초기 세팅
Zustand
Zustand는 클라이언트(UI) 상태를 관리하기 위해 사용한다.
설치
npm i zustandZustand를 선택한 이유
- 가볍고 간단함: 설정이 거의 없고 바로 store를 만들 수 있다.
- 보일러플레이트가 적음: action/reducer 같은 구조를 강제하지 않는다.
- React Hook처럼 사용 가능: 필요한 상태만 선택해 구독할 수 있다.
- 불필요한 리렌더링을 줄이기 쉬움: selector 기반으로 필요한 값만 가져온다.
보일러플레이트(Boilerplate)란?
보일러플레이트는 기능 자체보다 “구조를 맞추기 위해 반복 작성하는 코드”를 말한다. Redux 전통 방식에서는 아래를 반복 작성하는 경우가 많았다.
- action type
- action creator
- reducer
- store 설정
- Provider 감싸기
Zustand는 store를 만들고 바로 훅처럼 사용할 수 있어서, 같은 기능을 더 적은 코드로 구현할 수 있다.
import { create } from 'zustand';
type UiState = {
isOpen: boolean;
open: () => void;
close: () => void;
};
export const useUiStore = create<UiState>((set) => ({
isOpen: false,
open: () => set({ isOpen: true }),
close: () => set({ isOpen: false }),
}));const isOpen = useUiStore((state) => state.isOpen);Shadcn/ui
shadcn/ui는 “라이브러리처럼 가져다 쓰는 컴포넌트”라기보다는, 프로젝트 내부에 컴포넌트 코드를 생성해서 직접 관리하는 방식이다. Tailwind 기반이고 커스터마이징이 쉬워서 디자인 시스템을 만들기 좋다.
설치
# shadcn/ui 초기 설정
npx shadcn@latest init@types/node
# Vite 설정 파일에서 Node.js 전역 타입(path, __dirname 등)을 사용하기 위해 설치
npm install -D @types/nodeVite 설정 파일(vite.config.ts)에서 path, __dirname 같은 Node API를 쓰게 되는데, TypeScript가 Node 타입을 모르기 때문에 타입 패키지를 추가해준다.
- 특히 path alias(@/) 설정할 때 path.resolve(...)를 쓰는 경우가 많아서 같이 설정한다고 한다.
shadcn/ui를 선택한 이유
- Tailwind 기반이라 스타일 시스템이 한 번 잡히면 속도가 빠름
- 컴포넌트를 “코드로 소유” → 수정/확장/디자인 변경이 자유로움
- 디자인 일관성 유지
TanStack Query
TanStack Query는 서버 상태를 다루는 데 최적화된 라이브러리다.
API 응답 데이터는 UI 상태가 아니라 서버에서 온 상태이기 때문에 캐싱, 동기화, 재요청 전략을 명확하게 관리하는 것이 중요하다.
설치
# 서버 상태 관리 라이브러리
npm i @tanstack/react-queryDevtools (개발 중 캐시 확인)
# React Query 상태를 시각적으로 확인하기 위한 개발용 도구
npm install -D @tanstack/react-query-devtoolsESLint 플러그인
# TanStack Query 사용 시 실수를 방지하기 위한 ESLint 플러그인
npm i -D @tanstack/eslint-plugin-queryTanStack Query를 선택한 이유
- 캐싱이 기본값으로 제공되어 불필요한 요청을 줄일 수 있음
- 로딩/에러 상태를 패턴으로 깔끔하게 처리 가능
- refetch 정책, staleTime 등 데이터 신선도 전략을 코드로 관리 가능
- 서버 상태와 UI 상태 분리로 구조가 명확해짐
기본 옵션
프로젝트 성격에 따라 다르지만, 초기 세팅에서는 다음 옵션을 기본값으로 적용했다.
{
retry: 1,
refetchOnWindowFocus: false,
}옵션 의미
retry: 1
네트워크 오류 등 실패 시 1회만 재시도한다. → 반복 요청으로 인한 불필요한 트래픽과 UX 혼란을 줄이기 위함이다.refetchOnWindowFocus: false브라우저 탭 전환 시 자동으로 데이터를 다시 불러오는 기본 동작을 비활성화했다. → 의도치 않은 데이터 갱신과 불필요한 요청을 방지하기 위함이다.
이후 서비스 특성에 맞게 staleTime, gcTime, refetchOnReconnect 등을 추가 조정할 수 있다.
ESLint 규칙 적용 포인트 (Query 관련)
TanStack Query는 의존성 배열이나 queryKey 관리에서 실수가 잦아서, ESLint 규칙으로 초기에 막아두는 게 편하다. 또한 queryKey 일관성이 캐싱 품질을 좌우해서 초기에 규칙으로 잡아두는 게 도움이 된다고 한다.
// TanStack Query
'@tanstack/query/exhaustive-deps': 'error',
'@tanstack/query/no-unstable-deps': 'error',