- 최근 React-Query를 쓰는 회사들이 꽤 많음을 짐작할 수 있었다.
- 마침 종종 참고하던 강의에 React-Query 내용이 있어, 강의를 듣고 간단히 써본 것을 정리한다.
- 강의는 Udemy의 React - The Complete Guide 2024를 시청했다.
React-Query(Tanstack-query)
: HTTP 요청을 보내고, 백엔드 데이터와 프론트엔드의 UI를 동기화하게 해주는 서버 상태 관리 라이브러리.
- 서버에 요청을 보내는 것은 굳이 이 라이브러리를 쓰지 않아도 가능하지만, React-query를 사용하면 간편함과 다양한 이점을 얻을 수 있음.
- ex) 코드 길이 감소, 데이터 변경 시 자동으로 새 데이터 fetch, 데이터 캐싱 등...
- React-Query에서 직접 HTTP 요청을 보내는 것이 아닌, 요청 결과로 얻은 데이터와 에러, 로딩 상태, 캐싱 등을 담당하는 역할을 수행한다.
QueryClientProvider
: react-query를 사용하기 위해서는 App 컴포넌트를 QueryClientProvider로 감싸줘야 한다.
- QueryClientProvider는 client를 필수 prop으로 가지며, 여기에는 QueryClient 인스턴스를 넘긴다.
import { QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
/* ... */
</QueryClientProvider>
);
}
export default App;
useQuery
: 커스텀 훅이나 컴포넌트 내부에서 쿼리를 정의할 때 사용하는 React-query의 훅. 필수 인자로 아래의 목록을 받는다.
- queryKey: 각 쿼리의 고유한 키. 내부적으로 데이터를 다시 fetch하거나, 캐싱하거나, 어플리케이션 전체적으로 쿼리를 공유할 때 사용한다.
- queryFn: 데이터를 resolve 하거나 에러를 처리하는 함수. useQuery가 QueryFuntionContext 오브젝트*를 queryFn에 넘긴다.
- enabled: useQuery를 실행할지, 말지를 결정하게 하는 프로퍼티. 이걸 false로 설정하면 useQuery가 자동적으로 실행되지 않는다. 대신, useQuery 내부적으로는 data가 없는 것(아직 데이터를 가지고 오는 중)으로 판단, isPending을 true로 반환함.
- 이 때 isPending 대신 사용할 수 있는 것이 isLoading.
(참고: 링크)
- 이 때 isPending 대신 사용할 수 있는 것이 isLoading.
* QueryFunctionContext: 아래의 프로퍼티들을 갖는다.
- queryKey: useQuery의 그 키.
- signal: useQuery의 실행을 중단할 수 있게 해준다.
- meta: query에 대한 추가 정보를 넣을 수 있다.
- useQuery는 윈도우를 전환할 때마다 자동적으로 데이터를 다시 가져온다(=== 서버와 데이터를 동기화하는 것이 가능하다).
- 데이터를 알아서 캐싱하는 것이 가능하다.
- ex) useEffect를 사용하여 데이터를 가져올 경우, 페이지를 오갈 때마다 데이터를 그때그때 다시 fetch한다(따라서 빈 화면 혹은 로딩 UI가 보이게 될 것).
- useQuery를 사용하면 화면 전환 시 캐시된 데이터를 사용하기 때문에 바로 화면을 보여줄 수 있게 된다.
- useQuery의 필수 옵션인 queryKey는 동적으로 할당하는 것이 가능하다. 이 경우, React-query가 같은 query 안에서 서로 다른 데이터에 대해 각각 다른 키 값을 갖게 하는 것이 가능하다.
- useQuery는 위에서 언급한 isPending, isLoading, isError 및 data 등의 값을 반환한다.
- 요청의 현재 상태 및 요청의 결과로 서버로부터 받아 온 데이터 등을 확인할 수 있다.
// 아래의 useQuery는 요청 상태 및 에러, 요청한 데이터를 반환한다
const { data, isPending, isError, error } = useQuery({
queryKey: ["events", id], // 쿼리 키를 동적으로 할당할 수 있다
queryFn: ({ signal }) => fetchEvent({ id, signal }), // id값에 해당하는 이벤트를 가져오는 함수
});
useMutation
: 요청을 보내는 useQuery와 달리, 데이터 작성/삭제/변경 등에 사용되는 훅. 아래의 인자들을 받을 수 있다. useQuery와 달리 useMutation은 별도의 필수 key 값을 요청하지 않는다는 차이점 또한 있다.
- mutationFn: 데이터 작성/삭제/변경을 위해 실행할 함수.
- onSuccess: 요청이 성공적으로 수행되었을 때 실행할 함수.
- onMutate: mutation 함수가 실행되기 전에 실행되는 함수. mutation 함수가 받는 인자를 그대로 받는다.
- onSettled: mutation의 결과에 상관없이(즉, 성공했든 실패했든) 실행되는 함수.
- useMutation은 mutate 함수를 반환한다.
- mutate 함수를 사용해 어떤 곳에서든 서버 작업을 수행할 수 있게 한다.
// 아래의 useMutation은 mutate 함수, 요청 상태 및 에러를 반환한다
const { mutate, isPending, isError, error } = useMutation({
// mutationFn으로 새 이벤트를 서버에 작성하는 함수를 넘긴다
// 추후 useMutation이 반환하는 mutate 함수를 통해 원하는 곳에서 새 이벤트를 작성할 수 있다
mutationFn: createNewEvent,
});
QueryClient
: 공식 문서에서 설명하는 바에 따르면 캐시와 관련된 다양한 작업을 수행할 수 있다. (참고) 여기에선 강의에서 다룬 메서드들을 간단히 기록한다.
- invalidateQueries(): 인자로 전달한 Query key에 해당하는 쿼리들이 outdated 된 것으로 간주, 해당 쿼리들을 다시 refetch한다.
- ex) 위의 코드를 예시로, 특정 이벤트를 추가한 후에는 전체 이벤트 리스트가 변경되었으므로 이벤트 리스트를 가져오는 쿼리를 다시 refetch하도록 만들 수 있다.
const { mutate, isPending, isError, error } = useMutation({
mutationFn: createNewEvent,
// 추가 부분: 요청이 성공하면 events 쿼리 키를 갖는 쿼리들을 다시 refetch 시킨다
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["events"] });
},
});
- cancelQueries(): 전달받은 Query key에 해당하는 쿼리들을 취소시킨다.
- setQueryData(): 쿼리의 캐시된 데이터를 바로 업데이트하는 동기 함수.
- 서버 통신과 관련한 다양한 기능을 갖고 있어서 처음 써보는 입장에선 신기했던 편.
- 언젠가 적극적으로, 제대로 프로젝트에서 써보고 싶다는 생각이 든다.
'공부 > React & React Native' 카테고리의 다른 글
[React] Windowing으로 렌더링 성능 최적화하기 (0) | 2024.06.02 |
---|---|
React Testing에 대하여 (0) | 2023.11.22 |
Notifee 정리 (1) | 2023.05.20 |
[0814 ~ 0815] React-Native 강의 정리 (0) | 2021.08.16 |
[0812~0813] React-Native 강의 정리 (0) | 2021.08.14 |