React Query 의 staleTime 과 cacheTime 에 대한 차이를 알려주는 좋은 글을 봤다.
하지만 글로만 읽으니 제대로 이해한 것이 맞는지 의심이 들어 직접 라이브러리를 만져가면서 익혀보기로 했다.
우선 참고자료에서 알려주신 내용은 다음과 같다.
React Query의 라이프 사이클
- A 쿼리 인스턴스가 mount 됨
- 네트워크에서 데이터를 fetch 하고 A라는 query key로 캐싱함.
- 이 데이터는 fresh 상태에서 staleTime(기본값 0) 이후 stale 상태로 변경됨
- A 쿼리 인스턴스가 unmount 됨
- 캐쉬는 cacheTime (기본값 5min) 만큼 유지되다가 GC에 의해 삭제됨
- 만일 cacheTime 이 지나기 전에 A 쿼리 인스턴스가 새롭게 mount 되면, fetch가 실행되고 fresh한 값을 가져오는 동안 캐시 데이터를 보여줌.
staleTime
- 데이터가 fresh -> stale 상태로 변경되는데 걸리는 시간
- fresh 상태일때는 쿼리 인스턴스가 새롭게 mount 되어도 네트워크 fetch가 일어나지 않는다.
- 데이터가 한번 fetch 되고 나서 staleTime이 지나지 않았다면 unmount 후 mount 되어도 fetch가 일어나지 않는다.
cacheTime
- 데이터가 inactive 상태일 때 캐싱된 상태로 남아있는 시간
- 쿼리 인스턴스가 unmount 되면 데이터는 inactive 상태로 변경된다. 캐시는 cacheTime 만큼 유지된다.
- cacheTime 이 지나면 가비지 콜렉터로 수집된다.
- cacheTime이 지나기 전에 쿼리 인스턴스가 다시 마운트 되면, 데이터를 fetch하는 동안 캐시 데이터를 보여준다.
- cacheTime은 staleTime과 관계없이, 무조건 inactive 된 시점을 기준으로 캐시 데이터 삭제를 결정한다.
staleTime 실습
실제로 써보면서 익혀보자.
페이지는 A 와 B 로 분리 되어있고 API 요청은 A 컴포넌트에서만 이루어진다.
A.js
import React from "react";
import "./styles.css";
import { useQuery } from "react-query";
import axios from "axios";
import { Link } from "react-router-dom";
export const getTodo = () =>
axios.get("https://jsonplaceholder.typicode.com/todos/1");
export default function A() {
useQuery(["Todo"], getTodo);
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Link to="/B">hi</Link>
</div>
);
}
B.js
import React from "react";
import "./styles.css";
import { Link } from "react-router-dom";
export default function B() {
return (
<div>
<h1>Hello</h1>
<Link to="/A">hi</Link>
</div>
);
}
현재 useQuery 의 staleTime이 디폴트인 0초이기 때문에 다음과 같은 현상이 발생한다.
따라서 ReactQuery 의 캐싱을 제대로 활용하려면 staleTime을 적용해야한다.
이제 staleTime을 5000ms 로 설정해보자.
5초간은 fresh -> stale 로 상태 변화가 발생하지않으므로 fetch가 발생하지 않는다.
cacheTime 실습
cacheTime에 대해 알아보자. 이 글을 쓴 이유이기도 하다.
A.js
import React from "react";
import "./styles.css";
import { useQuery } from "react-query";
import axios from "axios";
import { Link } from "react-router-dom";
export const getTodo = () =>
axios.get("https://jsonplaceholder.typicode.com/todos/1");
export default function A(props) {
const { client } = props;
useQuery(["Todo"], getTodo);
console.log(client);
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
<Link to="/B">hi</Link>
</div>
);
}
B.js
import React from "react";
import "./styles.css";
import { Link } from "react-router-dom";
export default function B(props) {
const { client } = props;
console.log(client);
return (
<div>
<h1>Hello</h1>
<Link to="/A">hi</Link>
</div>
);
}
A 페이지에서 B 페이지로 이동해도 queryCache 에는 key 값이 Todo 인 Query가 존재한다.
지금 현재는 cacheTime 에 아무런 설정을 해주지 않아 디폴트인 5분이 적용된 상태이다.
만약 cacheTime 을 1000ms 로 설정하면 어떤 결과가 발생할까?
A 컴포넌트에서 unmount 가 발생하면 query 의 상태가 inactive 가 되기 때문에 1초후 GC에 의해 cache 가 삭제되게 된다.
콘솔을 확인해보면 캐시가 없어진 것을 확인할 수 있었다.
여담으로..
React Query 를 사용할때 App을 QueryClientProvider의 Child 로 내려주는 방식으로 사용한다.
이때 QueryClient 의 인스턴스의 데이터가 바뀌기 때문에 App이 리렌더가 되는 것을 확인 할 수 있었다.
내가 몰랐던 리렌더의 발생여부를 파악할 수 있었다.
import React from "react";
import { createRoot } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "react-query";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
const queryClient = new QueryClient();
root.render(
<QueryClientProvider client={queryClient}>
<App client={queryClient} />
</QueryClientProvider>
);
https://codesandbox.io/s/compassionate-solomon-sej412
'공부기록 > 웹 개발' 카테고리의 다른 글
Glitch 에 json-server 배포한 과정 (2) | 2023.03.10 |
---|---|
setState에 대해 고민했던 하루 (2) | 2023.02.10 |
[우아한 테크코스 프리코스] 1차 탈락 (4) | 2022.12.15 |
[우아한 테크코스 프리코스] 4주차 (0) | 2022.11.30 |
[우아한 테크코스 프리코스] 3주차 (0) | 2022.11.15 |