
우선 상품 데이터들을 dummy API를 이용하여 dummy data로 가져와보고, 상품에 따른 상세페이지도 구현해보자.
이때, React Query를 이용하여 데이터를 조회하도록 하자!
✅ 설치
yarn add react-query
QueryClient 인스턴스를 사용한다.// src/queryClient.ts
import { QueryClient } from "react-query";
export const getClient = (() => {
let client: QueryClient | null = null;
return () => {
if (!client) client = new QueryClient(); // 인스턴스 생성
return client;
};
})();
useQuery 훅 안에서 QueryClient 인스턴스에 접근할 수 있도록 QueryClientProvider를 컴포넌트 트리 상위에 추가해줘야 한다.// src/app.tsx
import { getClient } from "./queryClient";
import { QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
const App = () => {
const elem = useRoutes(routes);
const queryClient = getClient();
return (
<QueryClientProvider client={queryClient}>
{elem}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
};
export default App;
✚ ReactQueryDevtools
💡 참고하자!
👉 React Query HomePage
👉 React Query로 서버 상태 관리하기
✅ React Query의 캐싱개념은 stale과 cachetime을 통해 이루어진다.
React Query는 기본적으로 캐싱된 data를 stale한 상태로 여긴다. (참고)
stale의 사전적 의미는 신선하지 않는이라는 뜻을 가진다.stale이란 최신화가 필요한 데이터라는 의미로 stale한 상태가 되면 다음의 경우에 refetch 된다.💡 refetch 되는 조건
1️⃣ 새로운 query instance가 마운트 될 때 (= page를 이동 했다가 왔을 때)
2️⃣ 브라우저 화면을 이탈 했다가 다시 focus 할 때
3️⃣ 네트워크가 다시 연결될 때
4️⃣ 특별히 설정한 refetch interval에 의한 경우 (refetchInterval)
✅ 만약 해당 useQuery를 호출할 당시에 옵션으로 staletime을 따로 지정해주지 않는다면?
항상 캐싱되어 있는 데이터는 stale하다고 여기기 때문에 refetching을 하게 되어 서버에 계속적인 요청을 하게된다.
즉, staletime을 지정해주지 않고 쓴다면 react-query의 캐싱 기능을 제대로 활용할 수가 없다.
cacheTime
staleTime
refetchOnWindowFocus
refetchOnReconnect
refetchOnMount
✅ 상품리스트에서 상세페이지로 이동후 다시 상품리스트로 이동할 때 캐싱된 데이터를 불러오므로 새롭게 데이터를 불러오지 않는 것을 확인할 수 있다!
전체적인 cacheTime, staleTime은 만료 시간을 (Infinity으로 설정하여 API 추가 호출을 방지하고, 자주 데이터 통신이 오가는 부분에서 별도로 Time 설정을 해주자.
// queryClient.ts
...
client = new QueryClient({
defaultOptions: {
queries: {
cacheTime: infinity,
staleTime: infinity,
refetchOnMount: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
},
},
});
✅ 기본적으로 React Query는 queryKey를 통해 query cache와 상호작용이 가능하다.
<Example>
// 문자열
const res = useQuery('persons', queryFn);
// 배열 - 1
const res = useQuery(['persons'], queryFn);
// 배열 - 2
const res = useQuery(['persons', 'add Id'], queryFn);
// 배열 - 3
const res = useQuery(['add Id', 'persons'], queryFn);
// 배열 - 4
const res = useQuery(['persons', {type: 'add', name: 'Id'}], queryFn);
✅ 객체로 Key 관리
// src/queryClient.ts
export const QueryKeys = {
PRODUCT: "PRODUCTS",
};
💡 참고하자!
👉 React Query Key 관리
그렇다면 앞서 생성한 querykey를 어떻게 사용하면 될까? 바로 useQuery를 사용하면 된다!
✅ useQuery는 서버로부터 데이터를 조회해올 때 사용한다.
// 대표적으로 사용되는 3개의 인자
const { data, isLoading, error } = useQuery(queryKey, queryFn, options)
✅ queryFn
// src/queryClient.ts
const BASE_URL = "https://fakestoreapi.com";
export const fetcher = async ({ method,path,params}: {
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
path: string;
body?: any;
params?: any;
}) => {
try {
const url = `${BASE_URL}${path}`;
const fetchOptions: RequestInit = {
method,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": BASE_URL,
},
};
const res = await fetch(url, fetchOptions);
const json = await res.json();
return json;
} catch (err) {
console.error(err);
}
};
// src/pages/products/index.tsx
import { useQuery } from "react-query";
import { fetcher, QueryKeys } from "../../queryClient";
import { Product } from "../../types";
const ProductList = () => {
const { data } = useQuery<Product[]>(QueryKeys.PRODUCT, () =>
fetcher({
method: "GET",
path: "/products", //dummy api params
})
);
return (
<ul className="products">
{data?.map((product: Product) => (
<ProductItem {...product} key={product.id} />
))}
</ul>
);
};
export default ProductList;

import { Product } from "../../types";
import { useQuery } from "react-query";
import { fetcher, QueryKeys } from "../../queryClient";
import { useParams } from "react-router-dom";
const ProductDetail = () => {
const { id } = useParams(); // URL의 파라미터 가져오기
const { data } = useQuery<Product>([QueryKeys.PRODUCTS, id], () =>
fetcher({
method: "GET",
path: `/products/${id}`,
})
);
if (!data) return null;
return <ProductDetail item={data} />;
};
export default ProductDetail;

💡 참고하자!
👉 React Query의 useQuery에 대해 알아보기
💡 잠깐) dummy API
Mockup API라고 할 수 있는데, Mockup(모형) API Server는 말 그대로 가짜 API 서버이다.
클라이언트 요청에 실제 서버처럼 동작하기보다는 미리 저장된 데이터를 단순하게 돌려주는 형태이다. 다시 말해 이는 가짜 서버를 사용해 실제 서버와 통신하는 것처럼 만들 수 있다.
나는 핑 웹사이트 프로토타입을 위한
Fake Store Rest API를 사용하였다.
fakeStoreApi는 JSON 형식의 제품, 카트 및 사용자가 필요한 모든 유형의 쇼핑 프로젝트와 함께 사용할 수 있다.