React
React : TanStack Query 심화 (Query Cancellation)
고래고래00
2024. 6. 14. 14:39
Query Cancellation
- 다운로드 UI 가 있을 때, 또는 UX 저해시키는 불필요한 네트워크 요청을 제거하기 위해 사용
- 대용량 fetching을 중간에 취소하거나 사용하지 않는 컴포넌트에서 fetching이 진행 중이면 자동으로 취소
=> 불필요한 네트워크 비용 감소 - queryFn 의 매개변수로 Abort Signal 을 받을 수 있고, 이를 이용해서 Query 취소 가능
더보기
동작원리
let controller;
const url = "video.mp4";
const downloadBtn = document.querySelector(".download"); // 다운로드 버튼
const abortBtn = document.querySelector(".abort"); // 취소 버튼
// 다운로드 버튼 클릭시 fetchVideo 실행
downloadBtn.addEventListener("click", fetchVideo);
// 취소 버튼 클릭시 controller의 abort가 실행되면서 다운로드 취소
abortBtn.addEventListener("click", () => {
if (controller) {
controller.abort();
console.log("Download aborted");
}
});
// 다운로드 버튼 클릭시 실행
function fetchVideo() {
controller = new AbortController(); // AbortController로 생성하는 instance
const signal = controller.signal; // controller의 signal을 변수화
fetch(url, { signal }) // fetch의 두 번째 인자로 signal => 다운로드 취소할 준비
.then((response) => {
console.log("Download complete", response);
})
.catch((err) => {
console.error(`Download error: ${err.message}`);
});
}
https://developer.mozilla.org/en-US/docs/Web/API/AbortController
AbortController - Web APIs | MDN
The AbortController interface represents a controller object that allows you to abort one or more Web requests as and when desired.
developer.mozilla.org
사용 방법
QueryFunctionContext
queryFn 은 매개변수로 QueryFunctionContext 이란 객체를 받음
더보기
// queryFn에 getTodos를 넣을 때, 명시적으로는 아무 인자도 넣지않았지만
// TanStack-Query에서는 queryFnContext를 이미 인자로 주고 있었음
export const getTodos = async (queryFnContext) => {
const { queryKey, pageParam, signal, meta } = queryFnContext;
// queryKey: 배열형태의 쿼리키
// pageParam: useInfiniteQuery 사용 시 getNextPageParam 실행 시 적용
// signal: AbortSignal 을 의미 (네트워크 요청을 중간에 중단시킬 수 있는 장치)
// meta: query에 대한 정보를 추가적으로 메모를 남길 수 있는 string 필드
const response = await axios.get("http://localhost:5000/todos", { signal });
return response.data;
};
useQuery({
queryKey: ["todos"],
queryFn: getTodos,
})
// example: <div onClick={(event) => {}} 여기처럼 알아서 인자를 넣어주고 있었음
https://tanstack.com/query/latest/docs/framework/react/guides/query-functions
Query Functions | TanStack Query React Docs
Does this replace [Redux, MobX, etc]? react
tanstack.com
쿼리를 중간에 취소하는 경우 2가지
- 데이터를 가져오는 도중에 컴포넌트가 unmount 될 때
- 명시적(수동)으로 취소
페이지 컴포넌트 umount 시 Query 취소
API 요청 시 기본설정은 컴포넌트가 unmount 되도 네트워크 요청은 중단 X
GET 요청 시 abort signal 이 옵션으로 들어간 경우에만 unmount 시 자동으로 네트워크 취소
더보기
import axios from 'axios'
const query = useQuery({
queryKey: ['todos'],
queryFn: ({ signal }) =>
axios.get('/todos', {
// Pass the signal to `axios`
signal,
}),
})
// queryFn 안에서 queryFunctionCntext로부터받은 signal을 axios의 option객체에 signal을 넣어줌
// => 쿼리 취소(abort) 준비 끝 => unmount시 자동으로 취소
수동으로 Query 취소
더보기
const query = useQuery({
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
},
})
const queryClient = useQueryClient()
return (
<button
onClick={(e) => {
e.preventDefault()
queryClient.cancelQueries({ queryKey: ['todos'] })
}}
>
Cancel
</button>
)
// queryClient를 사용해 버튼 클릭시(수동) 쿼리 취소
주의사항
- 불필요한 네트워크 요청을 최소화 한다는 명분으로 단순하게
모든 GET 요청마다 Abort Signal 을 심는 것은 작업부하를 올림 - 동영상 다운로드 같은 대용량 fetching이 아닌 이상
대부분의 GET 요청은 빠르게 완료 및 캐싱처리되어 성능에 유의미한 영향 X - 대용량 fetching이 있는 경우 또는 Optimistic UI 를 구현할 때처럼 필요한 경우에만 적용