☑️ useQuery로 데이터 받아오기
useQuery 훅은 비동기 데이터를 쉽게 가져오는 방법을 제공한다. queryKey와 queryFn을 인자로 받아 데이터를 불러오고 이를 관리하는 역할을 한다.
queryKey- React Query에서 쿼리의 고유한 식별자 역할을 한다. 각 쿼리의 캐시를 관리하는 데 필요한 "이름표"와 같다.
queryKey는 문자열, 배열, 객체 등 다양한 형태로 지정할 수 있으며, 고유한 값만 있으면 된다.
queryFnqueryFn은 실제로 데이터를 가져오는 함수로,useQuery가 서버와 통신하여 데이터를 받아올 때 사용하는 비동기 함수이다. 주로 API를 호출하거나, 데이터베이스에 접근하는 함수가queryFn으로 사용된다.- React Query는 이
queryFn을 호출하여 데이터를 요청하고,queryFn에서 반환한 데이터를data에 저장한다.
import { useQuery } from "react-query";
function HomePage() {
const { data, error, isLoading } = useQuery({
queryKey: ["posts"],
queryFn: getPosts, // 비동기 데이터를 받아오는 함수
});
if (isLoading) return <p>로딩 중...</p>;
if (error) return <p>에러가 발생했습니다: {error.message}</p>;
return (
<div>
<h1>게시물 목록</h1>
<ul>
{data.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
☑️ 쿼리 상태(queryStatus)와 데이터 가져오기 상태(fetchStatus)
리액트 쿼리는 쿼리가 현재 어느 단계에 있는지 알려주는 다양한 상태를 제공하며 query status, fetch status 두 가지 status가 있다.
- query status : 실제로 받아 온
data값이 있는지 없는지를 나타내는 상태 값, 쿼리의 전체적인 상태를 표시 - fetch status :
queryFn()함수가 현재 실행 중인지 아닌지를 나타내는 상태 값, 데이터 요청의 구체적인 상태를 표시
✔️ Query Status
pending: 아직 데이터를 받아오지 못했을 때를 의미success: 데이터를 성공적으로 받아옴error: 데이터를 받아오는 중에 에러가 발생
이 상태 값들은 각각 isPending, isError, isSuccess와 매칭이 되어서, 이 값들을 이용해 현재 쿼리의 상태가 어떤지 확인할 수 있다.

const { data, status } = useQuery(...);
if (status === "loading") return <p>로딩 중입니다...</p>;
if (status === "error") return <p>에러가 발생했습니다.</p>;
if (status === "success") return <p>데이터가 성공적으로 로드되었습니다.</p>;
✔️ Fetch Status
fetching: 데이터를 가져오는 중일 때 표시(현재 쿼리 함수가 실행되는 중일 때)paused: 데이터 요청이 일시 중지된 상태(쿼리 함수가 시작은 했는데 실제로 실행되고 있지는 않을 때)idle: 현재 데이터 요청이 이루어지지 않는 상태, 데이터가 이미 캐싱되어 있어 별도의 요청이 필요 없는 경우
const { fetchStatus } = useQuery(...);
if (fetchStatus === "fetching") return <p>데이터를 불러오는 중입니다...</p>;
if (fetchStatus === "paused") return <p>네트워크 문제로 요청이 일시 중지되었습니다.</p>;
✔️ Query Status, Fetch Status의 흐름

- 처음으로 컴포넌트가 마운트되어
useQuery()가 실행 - 데이터를 아직 받아오지 못했기 때문에 query status는
pending상태, 쿼리 함수가 실행되면서 fetch status는fetching상태 - 만약 네트워크 상태가 오프라인일 때 쿼리 함수가 실행된다면, fetch status는
paused상태 - 데이터를 성공적으로 받았다면 query status는
success, 만약 데이터를 받아오는 과정에서 에러가 발생했다면error상태 - fetch status는 데이터를 성공적으로 가져왔는지 여부에 상관없이, 쿼리 함수의 실행이 끝나면
idle상태 - 그 후에 데이터를 서버에서 다시 받아오는 refetch 작업이 발생하면 쿼리 함수가 재실행되면서 다시
fetching상태
☑️ 캐싱 이해하기
✔️ 캐시(Cache)란?
캐시란 데이터를 미리 복사해 놓는 임시 장소를 말한다. 사이트에 접속했을 때 받아 온 데이터를 캐시 형태로 저장해서, 같은 사이트에 접속했을 때 캐시에 저장해 놓은 데이터를 유저에게 보여주는 것이다.
🤔 그럼 언제 데이터를 백엔드에서 다시 받아오는 refetch를 하고, 언제 캐시에 저장되어 있는 데이터를 보여주는 것일까?
우선 리액트 쿼리의 데이터 라이플 사이클을 알아보자
const { data, error, isLoading } = useQuery({
queryKey: ["posts"],
queryFn: getPosts, // 비동기 데이터를 받아오는 함수
});

이전 코드를 보면 ['post']라는 쿼리 키를 설정해주었는데, 여기에 우리가 받아 온 데이터가 캐시에 저장되어 있다.
(1) useQuery()가 실행되어 먼저 전달받은 쿼리 키로 저장된 데이터가 있는 지 확인하다.
(2) 데이터가 없으면 쿼리 함수queryFn()를 실행해 데이터를 백엔드로 받아오고 ['post'] 라는 쿼리 키로 데이터를 캐시에 저장한다. 이렇게 캐시에 저장된 데이터는 fresh상태에서 staleTime이 지나면 stale상태로 변경된다. (staleTime은 기본적으로 '0'으로 설정되어 있다.)
(3) 데이터가 있으면 캐시에 저장되어 있는 데이터를 리턴한다. 만약 데이터가 "신선한(fresh)" 상태라면 캐시에 저장된 데이터를 리턴하고 stale 상태면 백그라운드(자체적으로 알아서)에서 refetch를 진행한다. 그리고 백엔드에서 새로 받아 온 데이터로 기존의 ['post]로 저장되어 있는 데이터를 갱신한다.
(4) 컴포넌트가 언마운트되어서 데이터가 inactive 상태가 되면 gcTime(가비지 컬렉션 타임) 동안 캐시에 저장되어 있다가 그 이후에 가비지 콜렉터에 의해 삭제가 된다. (가비지 컬렉션 타임은 기본적으로 5분으로 설정되어 있다.)
💡 데이터가 stale상태면 네 가지 상황에서 refetch를 진행한다.
새로운 쿼리 인스턴스가 마운트 되거나(refetchOnMount), 브라우저 창에 다시 포커스가 가거나(refetchOnWindowFocus), 네트워크가 다시 연결되거나(refetchOnReconnect), 혹은 미리 설정해 둔 refetch interval 시간이 지났을 때(refetchInterval) refetch를 하게 된다. 이를 변경하고 싶다면 각각 옵션을 변경하면 된다.
☑️ 로딩과 에러 처리
아래는 isPending과 isError 값을 이용한 로딩과 에러 처리 예제 코드이다.
function HomePage() {
const {
data: postsData,
isPending,
isError,
} = useQuery({
queryKey: ['posts'],
queryFn: getPosts,
retry: 0,
});
if (isPending) return '로딩 중입니다...';
if (isError) return '에러가 발생했습니다.';
const posts = postsData?.results ?? [];
return (
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.user.name}: {post.content}
</li>
))}
</ul>
</div>
);
}
'React' 카테고리의 다른 글
| [React] React-Query(3) - useMutation() (3) | 2024.11.15 |
|---|---|
| [React] React-Query(1) - 소개 & 설치 (5) | 2024.11.08 |