React 라이브러리 조합 가이드: Zustand·TanStack Query·shadcn/ui 선택 기준

2025.12.07·수정 2026.07.20·약 10분

React 라이브러리 조합 선택 핵심 요약

React 프로젝트의 도구 선택은 유행 순위가 아니라 상태의 소유권, 서버 동기화, UI 접근성, 폼 검증을 분리하는 일입니다. 클라이언트 공유 상태는 Zustand나 Redux Toolkit, 서버 원본 데이터는 TanStack Query, 소유 가능한 UI 코드는 shadcn/ui, 낮은 수준의 접근성 primitive는 Radix를 우선 검토합니다. 단순한 화면은 React 자체 기능만으로 끝내는 선택도 정상입니다.

검증 기준: 2026-07-19, 각 프로젝트의 공식 최신 문서 기준입니다. 라이브러리는 빠르게 바뀌므로 실제 도입 전에는 package.json과 lockfile, 마이그레이션 문서를 다시 확인하세요. 이 글의 추천은 편집 판단이며 모든 팀에 통용되는 성능 보장은 아닙니다.

1. 상태 소유권부터 나누면 조합이 단순해집니다

React 프로젝트에서 로컬 상태, 공유 상태, 서버 상태와 UI 계층을 나누는 선택 흐름

컴포넌트 안에서 끝나는 값은 먼저 React에 둡니다

입력창 임시 값, 한 컴포넌트의 열림 상태, 가까운 부모·자식만 공유하는 값은 useState나 Context로 충분할 수 있습니다. 전역 store를 먼저 만들면 데이터의 실제 소유자가 흐려지고 테스트 범위가 커집니다. 여러 화면에서 같은 클라이언트 상태를 읽고 갱신해야 할 때만 외부 store를 검토합니다.

서버가 원본인 값은 일반 전역 상태와 분리합니다

상품 목록, 사용자 프로필, 게시글처럼 서버가 원본인 값에는 로딩·실패·재시도·캐시·재검증이 따라옵니다. 같은 응답을 Zustand와 TanStack Query 양쪽에 복사하면 어느 쪽이 최신인지 결정하기 어려워집니다. 서버 응답은 Query 캐시에 두고, 선택된 탭이나 편집 중 임시 값처럼 클라이언트가 소유한 상태만 store에 두는 편이 안전합니다.

2. 조건·장점·제약·권장 상황 비교표

React state, Zustand, Redux Toolkit과 TanStack Query를 상태 성격별로 비교하는 표
선택지 조건 장점 제약 권장 상황
React state·Context 범위가 작고 갱신 규칙이 단순함 추가 의존성 없음 빈번한 전역 갱신·복잡한 파생 상태에는 설계 부담 폼 일부, 모달, 테마처럼 좁은 상태
Zustand 여러 컴포넌트가 작은 클라이언트 상태를 공유 hook 기반 API와 적은 보일러플레이트 팀 규칙을 직접 정해야 하며 서버 캐시 기능은 목적이 아님 장바구니 UI, 필터, 편집기 임시 상태
Redux Toolkit 액션 흐름·미들웨어·DevTools·팀 규약이 중요 공식 권장 Redux 도구와 예측 가능한 구조 작은 앱에는 구조 비용이 더 큼 큰 팀, 복잡한 도메인 이벤트, 감사 가능한 변경 흐름
TanStack Query 원본이 API에 있고 캐시·재요청이 필요 서버 상태 생명주기를 일관되게 처리 query key·staleTime·무효화 규칙을 설계해야 함 목록·상세·사용자 정보·mutation 후 동기화

Zustand 공식 문서는 hook 기반 store와 selector 구독을 보여주고, Redux Toolkit은 현재 Redux 로직을 작성하는 표준 방식이라고 명시합니다. 실제 API와 팀 운영 방식은 Zustand 공식 문서, Redux Toolkit 시작 문서에서 확인하세요.

3. TanStack Query는 캐시 기본값과 무효화를 함께 설계합니다

stale과 삭제를 같은 개념으로 보지 않습니다

공식 기본값에서는 query 데이터가 기본적으로 stale로 취급되어 mount, 창 focus, 네트워크 재연결 같은 조건에서 백그라운드 refetch가 발생할 수 있습니다. staleTime은 “얼마 동안 새 데이터로 볼지”를 정하며, inactive query의 정리 시점은 별도 설정입니다. 요청이 많다는 이유만으로 캐시를 제거하기보다 데이터 변경 주기에 맞춰 staleTime을 먼저 조정합니다. 근거는 TanStack Query Important Defaults입니다.

mutation 성공 뒤에는 관련 query key를 명시적으로 무효화합니다

무효화는 일치하는 query를 stale로 표시하고, 현재 화면에서 관찰 중이라면 백그라운드 refetch를 유도합니다. 문자열을 여기저기 복사하지 말고 query key factory 또는 상수로 관리하면 빠뜨릴 가능성이 줄어듭니다. 공식 동작은 TanStack Query Query Invalidation에서 확인할 수 있습니다.

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';

const todosKey = ['todos'] as const;

export function TodoList() {
  const queryClient = useQueryClient();
  const todos = useQuery({
    queryKey: todosKey,
    queryFn: fetchTodos,
    staleTime: 60_000,
  });

  const addTodo = useMutation({
    mutationFn: createTodo,
    onSuccess: () => queryClient.invalidateQueries({ queryKey: todosKey }),
  });

  // 실제 UI에서는 loading/error/empty 상태를 각각 렌더링합니다.
  return null;
}

4. shadcn/ui와 Radix는 같은 층의 선택지가 아닙니다

shadcn UI의 소유 가능한 컴포넌트 코드와 Radix primitive 계층을 비교하는 구조

shadcn/ui는 설치 후 코드 소유권과 유지보수 책임을 함께 가져옵니다

shadcn/ui는 전통적인 단일 npm 컴포넌트 패키지라기보다 실제 컴포넌트 코드를 프로젝트로 배포하는 방식입니다. 커스터마이징이 쉽지만, 수정한 코드와 upstream 변경을 팀이 관리해야 합니다. shadcn/ui 공식 소개의 “Open Code” 설명을 기준으로 판단하세요.

2026년에는 “shadcn/ui는 항상 Radix 기반”이라고 단정하면 안 됩니다

공식 변경 기록은 Radix와 Base UI 중 primitive를 고를 수 있는 흐름을 안내합니다. 따라서 생성된 컴포넌트의 import와 CLI 설정을 확인해야 합니다. shadcn/ui 2026 Base UI 변경 기록을 기준으로 기존 설명을 교정했습니다. Radix 자체는 접근성·키보드·focus 관리에 집중한 낮은 수준의 primitive이며, 세부 역할은 Radix Primitives 공식 소개에서 확인할 수 있습니다. 어느 쪽을 쓰더라도 실제 라벨, 키보드 순서, 화면낭독기 동작은 제품 문맥에서 다시 테스트해야 합니다.

5. 폼은 필드 상태와 데이터 계약을 분리합니다

React Hook Form과 Zod를 필드 상태와 입력 데이터 계약으로 분리하는 흐름

검색창처럼 필드가 적으면 React state로 충분합니다. 필드가 많고 touched·dirty·오류 표시를 일관되게 다뤄야 하면 React Hook Form을 검토합니다. Zod는 런타임 입력을 파싱해 데이터 계약을 확인하는 도구입니다. 타입 추론만 믿지 말고 API 경계에서 실제로 parse하며, 서버도 별도로 검증해야 합니다. 시작 API는 React Hook Form 공식 시작 문서, Zod 공식 문서에서 확인하세요.

6. 도입 순서와 명시적 결론

React 라이브러리 도입 전 문제 정의, 최소 실험, 운영 기준과 회귀 검증 체크리스트
  1. 현재 문제를 “클라이언트 공유 상태·서버 상태·UI primitive·폼 계약” 중 하나로 분류합니다.
  2. React 자체 기능으로 해결 가능한지 먼저 확인합니다.
  3. 후보 하나로 작은 화면을 구현하고 번들·접근성·테스트·팀 학습 비용을 기록합니다.
  4. query key, store 경계, 컴포넌트 소유권, 스키마 위치를 짧은 결정 기록으로 남깁니다.
  5. 도입 후 사용하지 않는 중복 상태와 래퍼를 제거합니다.

결론: 서버 데이터가 있다면 TanStack Query 같은 서버 상태 계층을 먼저 정하고, 남은 클라이언트 공유 상태가 실제로 있을 때 Zustand 또는 Redux Toolkit을 선택하세요. UI는 빠른 출발보다 수정·업데이트 책임을 감당할 수 있는지를 기준으로 고릅니다. 다음 행동은 현재 화면의 상태 목록을 작성해 소유권 4종으로 분류하는 것입니다.

공식 근거와 다음 학습 경로

내부 학습 순서

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

“React 라이브러리 조합 가이드: Zustand·TanStack Query·shadcn/ui 선택 기준”에 대한 2개의 생각

댓글 남기기