react-query
에 가장 중요한 개념 중 하나가 바로 '캐싱'이다.
react-query를 사용하지 않고, 데이터 fetch를 하게 될 경우를 보자.
// fetch data using react-query
import axios from "axios";
import { useQuery } from "@tanstack/react-query";
import styles from "./RQProducts.module.css";
const Products = () => {
const fetchData = async () => {
const res = await axios.get("http://localhost:4000/products");
return res.data;
};
const { status, data, error } = useQuery(["products"], fetchData);
if (status === "loading") {
return <h1>Loading...</h1>;
};
if (status === "error") {
return <h1>Error: {error.message}</h1>;
};
return (
<>
<h1>React Query Products</h1>
{data &&
data.map((product) => {
return <li key={product.name}>{product.name}</li>;
})}
</>
);
};
export default Products;
1️⃣ useQuery
가 처음 "products"(query-key)
키를 실행하면, isLoading
이 true
로 설정된 후, 네트워크 요청이 전송되어 데이터를 가져오게 된다.
2️⃣ 요청이 완료되면, query-key
를 사용하여 캐싱되고 "products"
을 고유 식별자로 사용한다.
3️⃣ Products
페이지에서 main
페이지로 돌아간뒤, 다시 Products
페이지로 돌아올 경우, react-query
는 해당 쿼리에 대한 데이터가 캐시에 있는지 확인한다.
4️⃣ 만약, 데이터가 캐시에 있을 경우, 이 캐시된 데이터는 로드되지 않고 true로 설정되어 즉시 return 된다. 따라서 해당 페이지를 재방문할 경우, "Loading..." 이 더이상 보이지 않는 것이다.
5️⃣ 만약, react-query
가 서버 데이터가 변경되었고, 캐시는 최신 버전을 담고있지 않는걸 알게 되면, background refetch가 트리거된다.
그리고 fetch가 성공적으로 끝난다면, 데이터가 업데이트 된다.
위의 경우 isFetching
을 통해서 확인할 수 있다.
6️⃣캐시를 지우고 싶다면 {cacheTiem: 시간}
을 사용하면 된다.
const { status, data, error } = useQuery(["products"], fetchData{
cacheTime: 5000,
});
그럼 다시 메인페이지로 돌아갔다가 products 페이지로 돌아와도 Loading이 보이게 된다.
이 캐싱 개념은 stale
과 cachetime
을 통해서 이루어진다.
chachetime은 위에서 잠깐 언급했으니 간단하게 정리하고 넘어가겠다.
캐시에 저장된 데이터는 메모리에 남아있게 되는데, 이 캐시는 cacheTime만큼 유지가 된다.
react-query에서 설정한 default
값은 300000(5분)
으로, 만약 이 시간동안 사용하지 않으면, 메모리에 저장되는게 불필요하다고 판단해서 garbage collector가 수거해서 캐시에서 해당 쿼리가 삭제된다.
stale의 사전적인 의미는 "탁한", "신선하지 않은" 으로 해석된다.
즉, 데이터가 stale하다는 의미는 데이터가 신선하지 않아 업데이트가 필요하다는 뜻이 된다.
default 값은 0으로, 데이터를 fetch 한 즉시 해당 데이터는 stale한 상태가 된다.
만약, 서버 데이터가 변경이 될 경우, 브라우저의 데이터는 stale한 데이터이기 때문이다.
이런 경우, refetch가 필요한데, refetch가 되는 조건은 다음 아래와 같다.
refetchOnReconnect
refetchOnMount
refetchOnWindowFocus
refetchInterval
staleTime은 쿼리를 fetch한 이후, 데이터가 stale한 상태가 되는데까지 소요되는 시간.
💡 여기서 react-query
는 useQuery
를 통해서 데이터를 fetch할 경우, staleTime
을 따로 지정하지 않았을 때 캐시에 저장된 데이터는 stale하다고 생각해서 계속해서 refetch
를 하면서 서버에 요청을 한다.
만약 데이터가 자주 바뀌는 어플리케이션일 경우 staleTime
을 따로 지정하지 않아도 괜찮겠지만, 만약 잦은 변경이 없는 어플리케이션.일 경우 staleTime
을 지정하는 것이 서버의 부담을 줄일 수 있어 좋다.
staleTime
을 설정할 경우, cacheTime
역시 고려해야한다.cacheTime:
캐시에 저장된 데이터는 메모리에 남아있게 되는데, 이 캐시는 cacheTime만큼 유지가 된다.
default: 5분
staleTime:
쿼리를 fetch한 이후, 데이터가 stale한 상태가 되는데까지 소요되는 시간.
default: 0분
위처럼 staleTime
의 default값은 0분이기 때문에 데이터가 캐싱되어도 stale하지 않은, 즉 신선한 데이터가 하나도 없다.
따라서 staleTime
을 설정하지 않으면 아래의 영상처럼 data를 fetch하자마자 stale이 뜬다.
따라서 staleTime
을 설정하면 fresh
가 보인다.
이때 cacheTime
을 고려해서 설정해야한다.
만약 staleTime
을 길게 설정한다고 할지라도 cacheTime
이 짧으면, 캐시가 사라진다.
데이터가 stale한 상태가 되면 refetch를 통해 서버에 요청을 해야하는데, cacheTime으로 인해 캐시가 사라지면 refetch가 안되기 때문이다.