react-query 개념 및 useQuery
useQuery 훅을 활용하는 기본 방법과 staleTime, retry 옵션에 대해 실습 코드로 학습함.
React Query
React Query는 API 호출을 단순하게 만들어주고, 내부적으로 캐싱, 재시도, refetch 등 많은 걸 자동으로 처리함
useQuery 기본 형태
const { data, isLoading, isError } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
staleTime: 2000,
});queryKey
- 캐시를 구분하는 고유한 키
- 배열 형태 → 파라미터별로 조합 가능
queryFn
- 실제 데이터를 불러오는 비동기 함수
isLoading vs isFetching
- isLoading
- 쿼리를 처음 실행할 때만
true - 캐시된 데이터 없어서 최초 로딩 상태를 의미 ( 데이터 호출 실행 전)
- 보통 처음 화면 로딩 스피너에 사용
- isFetching의 하위 집합 개념임
- 쿼리를 처음 실행할 때만
- isFetching
- 쿼리가 실행되는 모든 순간
true - 처음 실행뿐 아니라 refetch(재요청) 중에도
true - 캐시가 있더라도 백그라운드에서 데이터를 다시 불러올 때 표시
- 새로고침 UI나 “업데이트 중” 표시 등에 적합
- 쿼리가 실행되는 모든 순간
요약
| 상태 | 의미 | 사용 예시 |
|---|---|---|
| isLoading | 최초 로딩 중 (캐시 없음) | 처음 데이터 요청 시 화면 로딩 |
| isFetching | 쿼리 실행 중 (캐시 상관없음) | refetch, 창 포커스 복귀 등 |
staleTime
- 데이터를 fresh 상태로 간주하는 시간(ms)
- 이게 왜 필요할까 - 과도한 refetch를 방지가 가능하다.
- 즉, API 호출(서버 비용?)을 줄이고 UX도 부드럽게 만들 수 있다
- 이 시간이 지나면 React Query는 refetch 가능 상태로 간주함
그러면 staleTime은 언제 유용한가?
- 브라우저 탭 이동 후 다시 돌아올 때
- 창 포커스 됐을 때
invalidateQueries로 직접 무효화했을 때
| 상황 | 예시 |
|---|---|
| 데이터가 자주 안 바뀌는 경우 | 지역 정보, 공지사항 등 |
| 데이터 실시간성이 중요한 경우 | 주식, 실시간 채팅 등 |
retry
- react-query는 기본적으로 총 3번 호출을 실행함
- 왜 3번 할까? 네트워크는 신뢰할 수 없기 때문에 일시적으로 자동 3번 재시도를 함
- 이 retry 옵션을 사용 하면 호출횟수를 지정할 수 있다
- 폼 전송 같은 건
retry: false로 꺼두는 게 안전함
자동 refetch 조건
전체 코드 예시
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { fetchPosts } from "./api";
import { PostDetail } from "./PostDetail";
export function Posts() {
const [selectedPost, setSelectedPost] = useState(null);
const { data, isLoading, isError } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
staleTime: 2000,
});
if (isLoading) return <h3>로딩중...</h3>;
if (isError) return <h3>에러 발생...</h3>;
return (
<>
<ul>
{data.map((post) => (
<li key={post.id} onClick={() => setSelectedPost(post)}>
{post.title}
</li>
))}
</ul>
<hr />
{selectedPost && <PostDetail post={selectedPost} />}
</>
);
}