안녕하세요, 똑똑한개발자에서 프론트엔드 개발을 하고 있습니다.
똑똑한개발자에서 사용하는 React-Query를 간단하게 소개하려고 합니다.
‘톺아보기’ 라는 말이 여전히 낯선 분들을 위해 한번 더 설명해보자면,
- 가파른 곳을 오르려고 매우 힘들여 더듬다
- 틈이 있는 곳마다 모조리 더듬어 뒤지면서 찾다
의 의미를 가진 우리말 단어입니다. 늘 그렇듯, 언제나 그렇듯 개발을 하며 겪는 모든 과정이 오류와 버그들을 ‘목표를 향해 가기 위해 매우 힘들여 더듬고, 모조리 더듬어 찾는’.. 톺아보는 과정이라고 생각합니다.
오늘은 React-Query를 톺아보도록 하겠습니다.
서버의 상태 관리를 위해 사용을 해봤지만, 많은 기능을 제공하고 있는 라이브러리이므로, 간단한 예제를 보신 후에 공식문서를 참고하시는것을 권해드립니다. 비교적 한국어 자료가 많이 없습니다. 도움이 되길 바랍니다.
프로덕트를 개발하며 여러가지 기능들을 구현하다보면,
서버에서 데이터를 불러오고, 내가 개발하는 리액트 어플리케이션의 데이터를 서버로 보내야 하는 등의 여러가지 API를 사용하게 되고, 이를 위해 정상적으로 페칭한 데이터의 관리는 물론,
로딩, 에러와 관련한 상태 또한 관리를 해야합니다. 기존의 데이터를 페칭하고
이것들을 관리하기위해 여러가지 훅을 사용해야했습니다.
const [data, setData] = useState([]);
const [isFetching, setIsFetching] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const state = {
// 로컬 상태
theme: "light",
sidebar: "off",
// 서버 상태
followers: [],
following: [],
userProfile: {},
messages: [],
todos: [],
};
기존의 데이터 관리 방식이라면 이 코드와 같이 여러가지 훅을 사용해야했고, 이와 같은 문제를 해결하고자 비동기 로직 처리 & 상태 관리와 관련된 많은 라이브러리들이 있습니다. (ex. Redux-saga) 그러나 이 경우에도 앱의 테마나 UI만을 위한 로컬 상태와 서버로부터 불러온 데이터가 뒤섞이는 문제가 생깁니다. 이러한 코드들은 불필요한 관리요소를 만듭니다. 이러한 데이터 페칭과 관련된 상태들을 좀 더 쉽고 간결하게 처리할수있게 도와주는 라이브러리가 바로 react-query 입니다.
시작하기 전에
예제를 보며 학습하기 전에 React-Query의 중요한 특징을 살펴보겠습니다.
-
다른 상태관리 라이브러리에서 요구하는 불필요한 boilerplate 코드 제거
React로 어플리케이션을 개발하며 상태관리를 할 때, redux와 같은 상태관리 라이브러리를 사용하게 되면, 로컬 상태관리와 서버상태의 관리를 한꺼번에 처리할 수 있습니다. React Query는 기본적으로 useQuery, useMutation과 같은 hooks API의 형태로 사용되며 서버의 상태를 다른장소(store)에 저장할 필요가 없습니다. 서버에서 가져온 데이터는 현재 위치와는 전혀 다른 위치의 컴포넌트에 전달해야 할 경우가 있습니다, 하지만 대부분의 경우 fetch요청을 수행한 컴포넌트와 1 ~ 2 단계의 하위 뎁스의 컴포넌트에서 사용하는 경우가 대부분입니다. 따라서, 서버 데이터 처리를 위한 redux-thunk, redux-saga와 같은 미들웨어, 별도의 비동기 처리로직을 작성할 필요가 없어 많은 양의 boilerplate 코드로 인한 피로감을 줄여주고, 서버상태를 별도로 관리해야하는 추가적인 관리요소 또한 불필요해집니다. -
Caching, Refresh 처리의 간편함 - 일반적인 REST API로 서버와 데이터를 주고받게 된다면, 업데이트와 같은 기능은 별도로 처리하여 직접 구현해야합니다. 그러나 React-query에서는 useQuery, useMutation의 파라미터를 통해 API 만료시간, 리프레시 기능을 수행할 간격, 성공, 에러, 로딩 처리 등의 다양한 기능을 사용할 수 있습니다.
설치
리액트로 제작된 모든 어플리케이션이 그러하듯 모든 시작은 의존성 라이브러리 설치에서 시작합니다.
본인이 사용하고 있는 패키지 관리툴에 맞는 명령어를 입력해주시면,
바로 설치가 진행됩니다.
$ yarn add react-query
**똑똑한개발자에서는 패키지 관리 도구로 Yarn을 주로 사용합니다.
or
$ npm i react-query
한 줄로 간편하게 설치해주시면, React-Query 사용할 준비가 완료됩니다.
Example
React-Query의 공식문서도 다른 라이브러리들이 그렇듯 매우 자세하게 설명되어있고,
예제 또한 심플합니다. 예제를 참고하면 직관적으로 이해 가능한 부분이 많지만,
빠른 이해를 위해 주석을 달겠습니다.
export default function App() {
{
/*리액트 어플리케이션의 메인이 되는 컴포넌트(_app.tsx / index.tsx)에
React-Query에서 제공하는 queryClient를 추가해주세요.*/
}
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
);
}
function Example() {
{
/*useQuery hook을 사용하여 Github의 React-Query 공식 repository의 정보들을 호출하는 API입니다. 데이터 호출을 위해 자주 사용하던 useState, useEffect 훅을 전혀 사용하지 않습니다. */
}
const { isLoading, error, data, isFetching } = useQuery("repoData", () =>
fetch("https://api.github.com/repos/tannerlinsley/react-query").then(
(res) => res.json()
)
);
if (isLoading) return "Loading...";
if (error) return "An error has occurred: " + error.message;
{
/* 앞서 이야기했듯 로딩, 에러상태와 관련된 처리를 별도로 해줄 필요가 없습니다.
React-Query에서 지원하는 기능을 사용하여 처리가 가능합니다. */
}
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>
);
}
해당 예제를 구현한 링크입니다. 참고해주세요. CodeSandBox
링크에서 한가지 특이한 것을 확인하실수가 있는데, 바로 react-query-devtool입니다.
네, 그렇습니다.
React-Query는 개발자의 편의를 위해 데이터 상태를 확인할 수 있는 별도의 devtool을 제공합니다. React-Query를 통해 처리되는 모든 작업을 시각화하고 데이터 처리를 위한 디버깅 시간을 훨씬 절약할수있습니다!
import { ReactQueryDevtools } from 'react-query/devtools'
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* The rest of your application */}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
몇 줄의 코드만 사용한다면, 훨씬 더 편한 디버깅 경험을 할 수 있습니다!
사용 후기
프론트엔드 개발을 하며 다양한 데이터를 다루게 되는 경험을 하게 됩니다. 로컬 상태관리와 서버에서 내려받은 상태관리가 생각보다 간단하지 않고, 지저분한 코드가 되기 쉽습니다. Redux나 mobx에 비해 비교적 사용방법이 간단하고, 직관적으로 이해하기가 좋았습니다. 개발자가 데이터를 처리할 컴포넌트를 지정만 해준다면 캐시처리, 리프레쉬, 업데이트 등을 간단하게 처리할 수 있습니다. 장황하게 쓰여진 useState, useEffect를 비롯한 boilerplate코드들,, 이번기회에 React-Query를 적용하여 좀 더 간결하게 코드를 구성하는 것은 어떨까요?