서버 상태를 위한 React Query
React Query(TanStack Query)를 사용하여 서버 측 데이터 가져오기, 캐싱, 동기화를 관리합니다.
서버 상태를 위한 React Query은(는) CoddyKit의 무료 Next.js 15 Fullstack Web Apps 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Next.js 15 Fullstack Web Apps 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Next.js 15 Fullstack Web Apps 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Meet React Query
React Query, now known as TanStack Query, is a powerful library for managing server-side state in your applications.
It helps you fetch, cache, synchronize, and update data in your React and Next.js apps effortlessly. Think of it as your data layer, handling the complexities of server data so you don't have to.
Benefits of TanStack Query
React Query solves many common data fetching challenges, making your app feel faster and more responsive:
- Caching: Stores fetched data to prevent unnecessary requests.
- Revalidation: Automatically refreshes stale data in the background.
- Loading States: Provides clear indicators for data fetching status.
- Error Handling: Simplifies managing and displaying fetch errors.
- Performance: Reduces network requests and improves user experience.
Initial Setup: Provider
To use React Query, you first need to set up a QueryClient and provide it to your app. This is typically done at the root of your application, wrapping your components with QueryClientProvider.
Here's how you might set up the client and provider in a Next.js app:
/* app/providers.jsx (or similar) */
"use client";
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import React from 'react';
const queryClient = new QueryClient();
export default function AppProviders({ children }) {
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}Your First Data Fetch
The useQuery hook is the core for fetching data. It takes two main arguments: a unique query key and an async query function.
The query key identifies your data in the cache. The query function actually fetches it. Try running this simple example fetching a user:
"use client";
import { useQuery } from '@tanstack/react-query';
import React from 'react';
async function fetchUser() {
const res = await fetch(
'https://jsonplaceholder.typicode.com/users/1'
);
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
}
export default function UserProfile() {
const { data, isLoading, error } = useQuery({
queryKey: ['user', 1],
queryFn: fetchUser,
});
if (isLoading) return <p>Loading user...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h3>User: {data.name}</h3>
<p>Email: {data.email}</p>
</div>
);
}Power of Query Keys
Query keys are crucial! They are like unique IDs for your cached data. React Query uses them to identify, refetch, and invalidate specific queries.
- Keys can be simple strings (e.g.,
'todos') or arrays. - Arrays are great for passing dependencies or parameters, like
['todos', { status: 'active' }]. - When a key's array elements change, React Query knows to refetch the data.
UI Feedback for Users
useQuery returns several useful states to manage your UI and provide feedback to users:
isLoading:truewhen the query is first fetching data.isError:trueif the query failed to fetch data.data: The successfully fetched data, orundefined.error: The error object ifisErroristrue.
These allow you to show loading spinners or error messages.
"use client";
import { useQuery } from '@tanstack/react-query';
import React from 'react';
async function fetchPost(id) {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
if (!res.ok) throw new Error('Fetch failed');
return res.json();
}
export default function PostDetail() {
const postId = 2; // Example ID
const { data, isLoading, isError, error } = useQuery({
queryKey: ['post', postId],
queryFn: () => fetchPost(postId),
});
if (isLoading) return <p>Loading post {postId}...</p>;
if (isError) return <p>Error: {error.message}</p>;
return (
<div>
<h4>Post {data.id}</h4>
<p>{data.title}</p>
</div>
);
}Smart Caching Behavior
React Query automatically caches data after a successful fetch. By default, data is considered "stale" immediately after fetching, meaning it might be refetched in the background when the component mounts or the window regains focus.
This "stale-while-revalidate" approach provides instant UI feedback with fresh data updates. You can configure staleTime to keep data "fresh" for longer, preventing unnecessary refetches.
Updating Server Data
While useQuery is for fetching, useMutation is for creating, updating, or deleting data on the server (e.g., POST, PUT, DELETE requests).
It provides a mutate function to trigger the server call, and also returns isPending (similar to isLoading), isError, and data for the mutation itself. Let's see an example of creating a new todo:
"use client";
import { useMutation } from '@tanstack/react-query';
import React from 'react';
async function addTodo(newTodo) {
const res = await fetch(
'https://jsonplaceholder.typicode.com/todos',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newTodo),
}
);
if (!res.ok) throw new Error('Failed to add');
return res.json();
}
export default function AddTodo() {
const mutation = useMutation({
mutationFn: addTodo,
onSuccess: (data) => alert('Added: ' + data.title),
onError: (error) => alert('Error: ' + error.message),
});
const handleAdd = () => {
mutation.mutate({ title: 'New task', completed: false });
};
return (
<div>
<button onClick={handleAdd} disabled={mutation.isPending}>
{mutation.isPending ? 'Adding...' : 'Add Todo'}
</button>
</div>
);
}Keeping Cache Fresh
After a mutation (e.g., adding a new item), your cached list of items might be outdated. You can use queryClient.invalidateQueries() to mark relevant queries as stale, which triggers a refetch for those queries.
This ensures your UI always reflects the latest server data. You typically call invalidateQueries in the onSuccess callback of useMutation.
"use client";
import { useMutation, useQueryClient } from '@tanstack/react-query';
import React from 'react';
async function createItem(newItem) {
const res = await fetch(
'https://jsonplaceholder.typicode.com/posts',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newItem),
}
);
if (!res.ok) throw new Error('Failed to create');
return res.json();
}
export default function CreateItemButton() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: createItem,
onSuccess: () => {
// Invalidate 'items' query to refetch the list
queryClient.invalidateQueries({ queryKey: ['items'] });
alert('Item created and list will refetch!');
},
});
const handleClick = () => {
mutation.mutate({ title: 'New Item', body: '...' });
};
return (
<button onClick={handleClick} disabled={mutation.isPending}>
{mutation.isPending ? 'Creating...' : 'Create Item'}
</button>
);
}Beyond the Basics
React Query offers many more advanced features to build highly performant and user-friendly data experiences:
- Optimistic Updates: Update UI before server response for instant feedback.
- Pagination/Infinite Queries: Efficiently load large datasets.
- Dependent Queries: Fetch data based on results of another query.
- Query Devtools: A browser extension for inspecting cache and queries.
Query Hook Check
You've learned about useQuery and useMutation.
Which of the following statements about React Query hooks are TRUE?
Lesson Summary
In this lesson, we explored React Query (TanStack Query), a powerful library for managing server state. You learned how to:
- Set up the
QueryClientProvider. - Fetch data using the
useQueryhook with query keys. - Handle loading and error states for a better UX.
- Mutate data on the server with
useMutation. - Keep your cache fresh by invalidating queries after mutations.
React Query significantly simplifies data fetching and synchronization, making your Next.js apps faster and more robust!
자주 묻는 질문
“서버 상태를 위한 React Query” 강의는 무료인가요?
네 — “서버 상태를 위한 React Query” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Next.js 15 Fullstack Web Apps 강의 전체를 잠금 해제할 수 있습니다. Next.js 15 Fullstack Web Apps 강의에는 총 4개의 강의가 포함되어 있습니다.
“서버 상태를 위한 React Query”에서 뭘 배우나요?
React Query(TanStack Query)를 사용하여 서버 측 데이터 가져오기, 캐싱, 동기화를 관리합니다. 브라우저에서 직접 실행하는 실습 코드로 Next.js 15 Fullstack Web Apps을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Next.js 15 Fullstack Web Apps을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Next.js 15 Fullstack Web Apps은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“서버 상태를 위한 React Query” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Next.js 15 Fullstack Web Apps 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Next.js 15 Fullstack Web Apps 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 서버 상태를 위한 React Query
- Zustand/Jotai를 사용한 클라이언트 측 상태
- 서버 측 캐싱 전략
- 낙관적 업데이트와 캐시 무효화