최근 배워서 사용하고 있는 TanStack Query에 대해 더 자세히 알기 위해 이 글을 작성합니다.
먼저 TanStack Query가 무엇인지 공식 페이지을 통해 알아보도록 하겠습니다.
웹 애플리케이션을 위한 데이터 가져오기 라이브러리로 서버 상태를 쉽게 가져오고, 캐시하고, 최신 데이터를 동기화하며 업데이트할 수 있게 해줍니다.
통합된 데이터 가져오기 방식 부재
대부분의 웹 프레임워크는 데이터 가져오기나 업데이트에 대한 통합된 방식을 제공하지 않기 때문에, 개발자들이 자체적으로 해결책을 만들어야 했습니다.
서버 상태 관리의 어려움
보통의 상태 관리 라이브러리는 클라이언트 상태 관리에는 적합하지만, 서버 상태 관리에는 적합하지 않습니다. 서버 상태는 원격 저장소에 저장되며, 비동기 API가 필요하고, 공유 소유권을 가지며, 데이터가 서버의 최신 데이터와 일치하지 않게 되는 상황이 생길 수 있기 때문에 관리가 어렵습니다.
복잡한 도전 과제
서버 상태를 관리하는 데는 캐싱, 중복 요청 제거, 데이터 업데이트, 성능 최적화 등 다양한 복잡한 도전 과제가 따릅니다.
아래는 TanStack Query의 기능들 중 중요성이 높은 내용들입니다.
캐싱
데이터를 로컬에 저장하여 동일한 데이터를 다시 요청할 때 서버로의 요청을 줄여 성능을 최적화
애플리케이션이 빠르게 응답할 수 있어 서버 부하 감소
중복 요청 제거
동일한 데이터를 여러 번 요청할 때, 이를 하나의 요청으로 통합하여 네트워크 자원을 절약
동시에 여러 컴포넌트가 같은 데이터를 필요로 할 때 유용
백그라운드 데이터 업데이트
예전 데이터를 백그라운드에서 자동으로 업데이트하여 사용자 인터페이스를 최신 상태로 유지
이는 사용자가 오래된 데이터를 보지 않도록 하며, 최신 정보 제공
이 단락에서는 useQuery hook를 사용하는 법을 알아보도록 하겠습니다.
npm install @tanstack/react-query 명령어를 통해 TanStack Query 라이브러리 설치
아래의 코드 처럼 QueryClientProvider를 이용하여 useQuery hook를 사용할 준비를 합니다.
import React from 'react';
import ReactDOM from 'react-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
// QueryClient 인스턴스를 생성
const queryClient = new QueryClient();
ReactDOM.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
document.getElementById('root')
);
범용적인 코어
TanStack Query의 코어는 프레임워크에 종속되지 않는 범용 JavaScript 라이브러리입니다. 따라서 React뿐만 아니라 다양한 프레임워크와 라이브러리에서도 사용할 수 있습니다.
React 바인딩
TanStack Query의 React 바인딩은 React Query입니다. 따라서 React Query 명칭을 우리가 알고 있는 것입니다.
React Query는 TanStack Query의 기능을 React 컴포넌트에서 쉽게 사용할 수 있도록 React의 훅 시스템을 활용합니다. 이에 따라 서버 상태를 관리할 수 있습니다.
QueryClient
QueryClient는 JavaScript로 작성된 TanStack Query의 핵심 클래스 중 하나로 데이터 fetching, 캐싱, 동기화 등의 서버 상태 관리 기능을 수행할 수 있습니다. React에서 사용하는 QueryClientProvider는 QueryClient 인스턴스를 애플리케이션 전역에서 공유할 수 있게 만들어 줍니다.
인자(Parameter)
쿼리 키(Query Key)
데이터를 가져오는데 사용되는 식별자
이는 쿼리의 고유한 식별자로 사용되며, 캐시와 관련된 동작에 영향
데이터 가져오기 함수(Query Function)
데이터를 가져오는 비동기 함수
이 함수는 데이터를 요청하고 응답을 처리하는 로직을 포함
옵션(Options)
선택적으로 전달되는 객체로, 캐싱, 재시도, refetch 등의 설정을 포함할 수 있음
반환값(Return Value)
데이터(Data)
비동기 함수에서 반환한 데이터
로딩 상태(isLoading)
데이터를 가져오는 중인지 여부를 나타내는 부울 값
데이터가 로딩 중이면 true, 그렇지 않으면 false
에러 상태(Error)
데이터를 가져오는 동안 발생한 에러 객체
캐시(Cache)
최신의 캐시된 데이터, 이 값을 통해 이전에 가져온 데이터를 즉시 사용 가능
재시도 함수(Refetch Function)
데이터를 다시 가져오는 함수
이 함수를 호출하면 새로운 데이터를 요청하고, 이전 데이터를 무시
import { useQuery } from '@tanstack/react-query';
const fetchRepoData = async () => {
const response = await fetch('https://api.github.com/repos/tannerlinsley/react-query');
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
};
const RepoData = () => {
// useQuery 훅을 사용하여 데이터를 가져옵니다.
const { data, error, isLoading } = useQuery(['repoData'], fetchRepoData);
// 데이터를 가져오는 중 일 때 렌더링하는 화면
if (isLoading) return <div>Loading...</div>;
// 데이터를 가져오는 중 에러가 발생했을 때 렌더링하는 화면
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<strong>{data.subscribers_count}</strong>
<strong>{data.stargazers_count}</strong>
<strong>{data.forks_count}</strong>
</div>
);
};
export default RepoData;
위의 fetchRepoData 함수를 보면 fetch를 통해 HTTP 요청 작업을 합니다. 이후 useQuery의 2번째 인자로 fetchRepoData를 사용하게 됩니다. 이를 통해 우리는 useQuery 자체에는 직접적인 HTTP 통신을 하는 기능이 내장되어 있지 않는 것을 알 수 있습니다.
useQuery는 데이터를 가져오는 로직을 담은 함수를 인자로 받아와서 해당 함수를 실행하고 그 결과를 관리하는 역할
위의 내용을 살펴보면 TanStack Query는 개발자 입장에서 서버의 데이터 관리를 도와주는 라이브러리인 것을 알 수 있었습니다. 여기서 저는 TanStack Query를 사용하는 이유가 또 있을지 생각해보고 찾아봤습니다.
데이터 패칭은 웹 애플리케이션에서 서버로부터 데이터를 가져오는 과정을 의미합니다. 여기서 크게 2가지 방식이 존재합니다.
명령형 방식 (Imperative)
명령형 방식에서는 코드가 데이터를 가져오는 과정을 명시적으로 나열하고 제어합니다. 명령형 방식에서는 데이터를 가져오는 과정에 대한 모든 세부 사항을 개발자가 명시적으로 제어해야 합니다. 이로 인해 코드가 복잡해지고 유지보수가 어려워질 수 있습니다.
선언적 방식 (Declarative)
선언적 방식에서는 코드가 데이터를 가져오는 과정을 설명하는 것에 집중됩니다. 즉, 원하는 데이터의 상태를 묘사하고, 시스템이 이를 어떻게 얻을지에 대한 세부 사항은 숨겨져 있습니다. 선언적 방식은 코드가 간결하고 읽기 쉽습니다. 또한, 코드가 데이터의 의도와 일치하므로 유지보수가 용이하고 오류 발생 가능성이 줄어듭니다.
즉, 선언적 방식은 원하는 데이터의 상태를 설명하고, 시스템이 이를 어떻게 가져올지에 대한 세부 사항을 추상화하여 개발자가 코드를 보다 직관적으로 작성할 수 있도록 하는 것을 의미합니다.
React Query의 useQuery 훅을 사용할 때, 개발자는 어떤 데이터를 가져오고자 하는지를 정의하는데 집중합니다. 이를 위해 필요한 것은 데이터 가져오기 함수와 쿼리 키를 제공하는 것뿐입니다. 이후 시스템은 이 정의된 상태를 기반으로 데이터를 가져오는 과정을 자동으로 처리합니다.
즉, Tanstack Query는 선언적인 방식으로 클라이언트 측 상태와 서버 상태를 자동적으로 동기화하기 때문에 개발자들 사이에서 많이 쓰는 라이브러리가 되었습니다.
이번 글작성을 통해 TanStack Query에 대해 공부했고, 더욱 깊게 공부하기 위해 '왜?'라는 문제의식을 가지도록 노력했습니다. 그로 인해 더욱 많은 정보를 알 수 있어 좋은 시간을 가지게 되었습니다.