frontend/react

[React] React.js 실무 강좌 37. React Query 캐싱 — 화면 전환 시 깜빡임 없이 데이터 유지하기

mirabo01 2025. 11. 11. 08:53

React Query를 써본 사람이라면 한 번쯤 이런 경험이 있을 겁니다.
목록 페이지에서 디테일 페이지로 갔다가 뒤로 돌아오면,
목록이 다시 로딩되면서 화면이 살짝 깜빡이는 현상.
성능 문제는 아닌데, 이 작은 깜빡임이 서비스 완성도를 확 떨어뜨립니다.

저도 초반엔 단순히 “UX가 살짝 어색하네” 정도로 넘겼는데,
결국 이걸 해결하려면 React Query의 캐싱 동작을 이해하는 게 핵심이었습니다.


왜 깜빡이는 걸까

React Query는 기본적으로 데이터를 캐싱합니다.
그런데 캐시라고 해서 무조건 영구 저장되는 게 아닙니다.
데이터는 staleTime과 cacheTime에 따라 언제든지 만료될 수 있습니다.

  • staleTime: 데이터가 ‘신선한(fresh)’ 상태로 유지되는 시간
  • cacheTime: 데이터가 ‘비활성화된 후’ 캐시에 남아있는 시간

즉, staleTime이 0이면 React Query는 화면이 다시 렌더링될 때마다
“이 데이터는 오래됐어”라고 판단하고, 새로 요청을 보냅니다.

이게 바로 깜빡임의 원인이죠.


staleTime을 적절히 조절하기

저는 보통 이렇게 설정합니다.

const { data, isLoading } = useQuery({
  queryKey: ['users'],
  queryFn: fetchUsers,
  staleTime: 1000 * 60 * 5, // 5분 동안 신선한 상태 유지
});

이 설정만으로도 뒤로 가기 시 로딩이 거의 사라집니다.
React Query는 데이터를 다시 요청하지 않고,
기존 캐시를 즉시 반환하기 때문입니다.

그리고 staleTime이 지나면 다음 렌더링 시점에 새로 데이터를 받아옵니다.
즉, 화면 전환이 부드러워지면서도 데이터의 신선도는 유지되는 구조입니다.


이걸 모르고 한참 헤맸던 시절

한동안 cacheTime을 staleTime이랑 헷갈려서 잘못 썼습니다.
cacheTime을 짧게 잡아놓으면, 탭을 이동하고 30초만 지나도
데이터가 캐시에서 사라져서 다시 로딩되곤 했어요.

캐시 관련 옵션은 이렇게 구분하면 깔끔합니다.

옵션 역할 기본값 특징

staleTime 데이터의 신선도 유지 시간 0 이 시간이 지나면 새로 요청
cacheTime 비활성 쿼리의 캐시 유지 시간 5분 이 시간이 지나면 캐시 삭제

정리하자면,
staleTime은 다시 요청할지 여부,
cacheTime은 캐시를 언제 버릴지 결정하는 값입니다.


화면 전환이 잦은 서비스라면

React Query의 캐싱 전략은 서비스 특성에 따라 달라야 합니다.

  • 뉴스, 주식, 실시간 데이터: staleTime을 짧게 (30초~1분)
  • 관리자 페이지, 목록 기반 서비스: staleTime을 길게 (5분~10분)
  • 유저 프로필이나 설정 페이지: 거의 변경되지 않으므로 staleTime을 Infinity로

예를 들어, 관리자용 목록 페이지라면 아래처럼 설정합니다.

useQuery({
  queryKey: ['admin-users'],
  queryFn: fetchAdminUsers,
  staleTime: 1000 * 60 * 10,
  cacheTime: 1000 * 60 * 30, // 30분 유지
});

이렇게 하면 리스트 페이지를 드나들어도
데이터는 그대로 유지되고, API 호출 수도 확 줄어듭니다.


React Query Devtools로 감 잡기

캐시가 실제로 어떻게 움직이는지 감을 잡으려면
React Query Devtools를 꼭 켜보세요.

yarn add @tanstack/react-query-devtools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

<QueryClientProvider client={queryClient}>
  <App />
  <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>

이걸 켜면 현재 쿼리 상태, 캐시된 데이터,
stale 상태 여부까지 전부 한눈에 보입니다.

저도 한참 동안 ‘왜 캐시가 바로 사라지지?’ 하면서 로그만 찍다가
Devtools로 확인하고 나서야 완전히 이해했습니다.


실무에서 얻은 결론

React Query의 캐싱은 단순히 ‘속도 최적화’가 아닙니다.
사용자 경험을 설계하는 도구입니다.
새로고침 없이 화면이 자연스럽게 이어지는 감각,
그게 작은 서비스 퀄리티 차이를 만듭니다.

캐시를 이해하고 다루기 시작하면
React Query가 단순한 비동기 툴이 아니라
‘데이터 생명주기 관리 라이브러리’라는 걸 실감하게 됩니다.


다음 글에서는 캐싱의 확장 버전인
React Query의 prefetch 기능을 이용해
“사용자가 클릭하기 전에 데이터를 미리 불러오는 기법”을 다뤄보겠습니다.
UX 개선과 체감 속도 면에서 꽤 재미있는 결과를 볼 수 있을 겁니다.