[React] React.js 강좌 18. 대시보드 구현 – React Query로 사용자 데이터 효율적으로 불러오기
1. 로그인 후 보여지는 대시보드란?
로그인 시스템을 구축했다면,
다음 단계는 **로그인한 사용자의 데이터를 시각적으로 보여주는 대시보드(Dashboard)**입니다.
예를 들어 다음과 같은 정보가 표시됩니다.
- 로그인한 사용자의 이름, 이메일, 가입일
- 최근 활동 내역
- 알림, 메시지, 통계 등
이 페이지는 서버에서 **로그인된 사용자 정보(API)**를 가져와야 하며,
데이터 갱신이 잦기 때문에 React Query를 사용하는 것이 가장 효율적입니다.
2. 기본 구조
대시보드 페이지를 구현하기 위해 다음 세 가지가 필요합니다.
1️⃣ 사용자 인증 토큰을 포함한 API 요청
2️⃣ React Query의 useQuery로 데이터 가져오기
3️⃣ 로딩/에러/성공 상태에 따른 UI 처리
3. API 요청 설정
Axios를 사용할 때,
모든 요청에 인증 토큰을 자동으로 포함시키면 편리합니다.
// api.js
import axios from 'axios';
const api = axios.create({
baseURL: '/api',
});
api.interceptors.request.use((config) => {
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export default api;
이제 api.get()을 호출하면
자동으로 Authorization 헤더가 포함됩니다.
4. React Query로 사용자 데이터 가져오기
import { useQuery } from '@tanstack/react-query';
import api from './api';
function Dashboard() {
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ['userProfile'],
queryFn: async () => {
const res = await api.get('/me');
return res.data;
},
});
if (isLoading) return <p>로딩 중입니다...</p>;
if (isError) return <p style={{ color: 'red' }}>데이터를 불러오지 못했습니다.</p>;
const { name, email, createdAt, recentActivity } = data.user;
return (
<div style={{ padding: '20px' }}>
<h2>대시보드</h2>
<div style={{ marginBottom: '20px' }}>
<h3>👋 {name}님 환영합니다.</h3>
<p>이메일: {email}</p>
<p>가입일: {new Date(createdAt).toLocaleDateString()}</p>
</div>
<section>
<h3>최근 활동</h3>
{recentActivity.length === 0 ? (
<p>최근 활동 내역이 없습니다.</p>
) : (
<ul>
{recentActivity.map((act, i) => (
<li key={i}>{act}</li>
))}
</ul>
)}
</section>
<button onClick={() => refetch()} style={{ marginTop: '20px' }}>
데이터 새로고침
</button>
</div>
);
}
export default Dashboard;
작동 설명
- queryKey: 데이터를 구분하는 식별자 (['userProfile'])
- queryFn: 실제 API 호출 함수
- refetch: 버튼 클릭 시 데이터 강제 갱신
5. 데이터 갱신과 자동 리페칭
React Query는 다음과 같은 상황에서 데이터를 자동으로 리페칭(refetch) 합니다.
- 브라우저가 다시 포커스될 때
- 네트워크 연결이 복구될 때
- invalidateQueries()가 호출될 때
예를 들어 로그인 후 사용자 정보를 최신으로 유지하고 싶다면,
로그인 성공 시 다음을 실행하면 됩니다.
queryClient.invalidateQueries(['userProfile']);
이렇게 하면 React Query가 자동으로 /api/me를 다시 호출합니다.
6. 로딩 상태 개선 (Skeleton UI)
로딩 중일 때 단순히 “로딩 중입니다”라는 문구 대신
Skeleton UI를 보여주면 사용자 경험이 훨씬 좋아집니다.
function LoadingSkeleton() {
return (
<div style={{ padding: '20px', opacity: 0.6 }}>
<div style={{ background: '#ddd', height: '20px', width: '40%', marginBottom: '10px' }} />
<div style={{ background: '#ddd', height: '15px', width: '60%', marginBottom: '10px' }} />
<div style={{ background: '#ddd', height: '15px', width: '80%', marginBottom: '10px' }} />
</div>
);
}
if (isLoading) return <LoadingSkeleton />;
이렇게 하면 데이터 로딩 중에도 깔끔한 UI 유지가 가능합니다.
7. React Query Devtools로 상태 확인
React Query의 캐시, 로딩 상태, 쿼리 갱신 현황을 시각적으로 확인하려면
Devtools를 추가하면 됩니다.
npm install @tanstack/react-query-devtools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
<QueryClientProvider client={client}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
이제 브라우저에서 쿼리 상태를 실시간으로 확인할 수 있습니다.
8. React Query 캐시 활용
React Query는 데이터를 자동으로 캐싱합니다.
즉, 사용자가 페이지를 다시 방문하더라도
staleTime 내에서는 네트워크 요청 없이 기존 데이터를 사용합니다.
useQuery({
queryKey: ['userProfile'],
queryFn: fetchUser,
staleTime: 1000 * 60 * 5, // 5분 동안 캐시 유지
});
이는 특히 대시보드처럼 자주 접근하는 페이지에서 매우 효과적입니다.
9. 에러 처리 전략
API 요청 중 오류가 발생할 경우를 대비해
서버 메시지를 그대로 보여주는 것이 좋습니다.
if (isError) {
return (
<div style={{ color: 'red' }}>
서버 오류가 발생했습니다.<br />
관리자에게 문의해주세요.
</div>
);
}
또는 React Query의 onError 콜백을 이용해
전역 에러 핸들러를 구성할 수도 있습니다.
const client = new QueryClient({
defaultOptions: {
queries: {
onError: (err) => console.error('쿼리 에러:', err),
},
},
});
10. 마무리
이번 강의에서는 로그인 이후 보여지는 사용자 대시보드를
React Query를 이용해 구현했습니다.
핵심 요약:
- Axios Interceptor로 토큰 자동 처리
- useQuery로 사용자 정보 불러오기
- 자동 리페칭과 캐시를 활용한 효율적 데이터 관리
- Skeleton UI로 UX 향상
React Query를 이용하면 서버와의 데이터 동기화를 직접 관리하지 않아도 되므로,
복잡한 상태 관리 없이도 최신 데이터를 유지하는 안정적인 대시보드를 만들 수 있습니다.
다음 강의에서는 React Router를 활용한 다중 페이지 대시보드 구조를 만들고,
라우트 간 데이터 캐싱과 전환 최적화 방법을 알아보겠습니다.