웹사이트에서 사용하는 상태 데이터는 크게 클라이언트 상태 데이터와 서버 상태 데이터로 나눌 수 있다.
클라이언트 상태 데이터는 웹사이트의 어떤 메뉴가 열렸는지 닫혔는지, 혹은 사용자가 어떤 버튼을 눌렀는지 아닌지와 같은 UI 상태 값이나, 유저가 입력 폼에 입력한 데이터 등 서버와는 상관없이 웹 브라우저 안에서만 사용하는 데이터.
서버 상태 데이터는 서버에서 가져오는 데이터. 예로, 네이버에 접속했을 때 우리가 보는 뉴스 기사나 각종 글은 모두 서버에서 받아오는 서버 상태 데이터이다.
서버 상태 데이터는 몇 가지 특징을 가지고 있다. 서버에서 데이터를 받아오기까지 시간이 걸리기 때문에 데이터를 받아오는 걸 비동기식으로 구현한다. 실제로 데이터를 받아 오기까지 플레이스 홀더를 보여주거나 로딩 처리를 한다. 데이터를 받아 오는 과정에서 에러가 생길 수 있기 때문에 이런 상황을 어떻게 처리하고 어떤 식으로 유저에게 안내해 줄 것인지에 대한 고민도 필요하다.
또한 서버 상태 데이터는 가능한 최신 상태로 유지되어야 한다. 데이터는 한 번 받아 오면 끝나는 게 아니라, 최신 데이터를 가능한 한 계속 받아 와야 한다. (사이트의 성격에 따라 얼마나 최신으로 데이터를 유지해야 하는지 달라짐) 예를 들어, 주식 사이트의 경우 1초 1초가 중요하므로 실시간으로 데이터를 받아오는 게 중요하고, 어떤 사이트는 1분에 한 번 혹은 5분에 한 번만 데이터를 받아오는 것으로 충분할 수 있다.
이런 서버 상태 데이터의 특징들 때문에, 클라이언트 상태 데이터를 사용할 떄와 달리 다양한 시나리오를 고민하고 관리해야 한다. 데이터를 받아오는 중에는 어떤 화면을 보여줄 것인지, 로딩과 에러 상황은 어떻게 할 수 있을지, 서버로부터 받아 온 데이터들은 어떻게 관리할지, 데이터를 주기적으로 받아오려면 어떤 식으로 구현해야 할지 등등.. 기존의 Redux 같은 라이브러리에서는 이런 서버 데이터들의 특성에 맞게 구현하고 데이터들을 관리하는 게 쉽지 않았지만, 이런 상황을 해결하기 위해 리액트 쿼리가 등장했다.
리액트 쿼리는 데이터를 가져오는 상태에서 로딩과 에러 처리를 쉽게 구현할 수 있도록 여러 값을 제공해 주고, 정해진 시간 혹은 조건마다 서버 상태 데이터를 최신으로 가져오는 작업도 알아서 해준다. 그뿐만 아니라 캐시(cache)라는 걸 사용해서 매번 서버에서 데이터를 가져올 필요 없이 유저에게 더 빠르게 데이터를 보여주기도 한다.
그 외에도 리액트 쿼리는 페이지네이션이나 Infinite Query, Optimistic Update와 같은 웹사이트들에서 자주 사용하는 기능을 손쉽게 구현할 수 있도록 해준다.
새 프로젝트 생성
npx create-react-app .
리액트 쿼리 설치
npm install @tanstack/react-query
QueryClient, QueryClientProveder
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import HomePage from './HomePage';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<HomePage />
</QueryClientProvider>
);
}
export default App;
QueryClient
를 생성QueryClientProvider
를 통해 자손 컴포넌트에 전달React Context
와 유사한 패턴!react-query
가 아닌 최신 버전의 @tanstack/react-query
에서 하시오리액트 쿼리를 사용해 개발을 할 때 매우 편리한 개발자 도구. 다음 명령어를 입력해 설치한다.
npm install @tanstack/react-query-devtools
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import HomePage from './HomePage';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<HomePage />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
export default App;
initialIsOpen
은 리액트 쿼리 개발자 도구가 열려있는 채로 실행할 것인가를 선택하는 옵션npm start
를 입력해 앱을 실행하면 오른쪽 하단에 플로팅 버튼이 생겨있다.