React

[React] react-query의 개념 및 사용법

킹우현 2023. 2. 20. 00:03

1) React Query 란 ?

React Query는 리액트 애플리케이션에서 서버의 데이터를 조회하거나 캐싱, 업데이트, 에러 처리와 같은 비동기 로직을 지원하는 fetching 라이브러리입니다. Server-side와 Client-side 사이에서 비동기 로직을 보다 쉽게 다루게 해주며 Server State를 관리해줍니다. 

 

리엑트 쿼리는 서버에서 가져온 데이터를 웹 브라우저 앱에서 사용하기 쉽게 도와주는 기술입니다.

 

서버는 클라이언트에게 데이터베이스에 있는 정보를 전달해주는 역할을 하는데요, 여기서 서버는 api 서버, 클라이언트는 웹 브라우저에서 실행되는 우리가 작성한 리액트 앱을 의미합니다.

 

DB에서 가져온 데이터를 클라이언트에서 보여주기 위해 우리는 ajax를 이용하는데요, 이 때 서버에서 가져오는 데이터를 서버의 상태라고 이야기 합니다.

 

React Query에서는 Server State를 다음과 같이 정의합니다.

  • Client가 제어하거나 소유하지 않는 위치에서 원격으로 유지 됨.
  • fetching 및 updating을 위한 비동기 API를 필요로 함.
  • 상태가 공유되며 사용자 모르게 변경될 수 있음.
  • 주의하지 않으면 애플리케이션이 잠재적으로 "out of date" 상태가 될 수 있음.

 

React Query는 앞서 언급한 Server State의 관리 기능을 포함하여 아래와 같은 특징도 가지고 있습니다.

  1. 캐싱(Caching) 기능 지원
  2. 동일한 데이터에 대한 중복 요청을 제거하고 한 번만 요청하도록 함(변경 시에만 리렌더링)
  3. "out of date" 상태의 데이터를 파악하고 updating 지원
  4. Pagination 및 Lazy Loading 성능 최적화
  5. Server State의 메모리 관리 및 garbage collection 지원
  6. React Hooks와 유사한 인터페이스 제공

 

2) React Query의 서버 상태(Server State) 모델링 과정

 

  • Fetching
    초기 상태이며 백엔드와 같은 외부 소스로부터 데이터를 가져오기 위해 동작.
  • Fresh
    Fetching 이후에 Server-side와 Client-side의 데이터가 동일하게 유지되는 상태.
  • Stale
    데이터가 오래된 상태이며 Fetching을 통해 Fresh 상태로 유지해줘야 함.
  • Inactive
    애플리케이션에서 사용되지 않는 데이터에 대한 상태.
    React Query에서 브라우저 캐시를 관리하는 가비지 컬렉터에 의해 삭제 됨.
  • Deleted
    Inactive 상태의 데이터가 캐시에서 삭제된 상태.

 

3) React Query Setting

 

3-1) React Query 설치

npm i react-query

yarn add react-query

 

 

3-2) QueryClientProvider

QueryClientProvider는 리액트 애플리케이션에서 비동기 요청을 처리하기위한 Context Provider로 동작하며 하위 컴포넌트에서 QueryClient를 사용할 수 있게 해줍니다.

 

index.tsx 파일에 React Query를 다음과 같이 설정해줍니다.

/* index.tsx */

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import { QueryClient, QueryClientProvider } from 'react-query';

const queryClient = new QueryClient();

ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

3-3) QueryCache

QueryCache는 React Query를 이용하여 사용된 쿼리의 메타 정보와 상태 등의 데이터를 저장하는 용도로 사용합니다.

 

또한 onError, onSuccess 콜백을 사용하여 애플리케이션 전역에서 이벤트를 핸들링 할 수 있습니다.

 

QueryCache 사용을 위해 index.tsx 파일에서 QueryClient 부분을 아래와 같이 설정해줍니다.

/* index.tsx */

import { QueryClient, QueryClientProvider, QueryCache } from 'react-query';

const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error, query) => {
      console.log('onError', error);
    },
    onSuccess: (data) => {
      console.log('onSuccess', data);
    }
  })
});

 

4) React Query API

React Query를 이용한 API 사용 방법에 대해 알아보겠습니다.

 

4-1) useQuery Hook

useQuery는 서버에서 데이터를 가져오기(get) 위해 사용하는 hook 입니다. unique key, promise 기반의 함수, Option 값을 파라미터로 받아서 동작합니다.

 

unique key는 애플리케이션 전역에서 해당 쿼리를 refetching, caching, sharing 하는 용도로 사용되며, 쿼리의 리턴 값으로는 status, data, error와 같은 템플릿을 포함하여 데이터 사용에 필요한 정보가 제공됩니다.

 

다음과 같이 기본적인 쿼리의 상태(status)와 프로퍼티를 사용할 수 있습니다.

  • isLoading
    쿼리에 데이터가 없고 fetching 하는 상태.
  • isError
    쿼리에 에러가 발생한 상태.
  • isSuccess
    쿼리가 성공적으로 실행되었고 데이터를 사용가능한 상태.
  • isIdle
    쿼리를 사용할 수 없는 상태. (disabled)
  • error
    쿼리가 isError 상태인 경우 에러 정보 확인을 위해 사용하는 프로퍼티.
  • data
    쿼리가 isSucess 상태인 경우 데이터 사용을 위해 사용하는 프로퍼티.
  • isFetching
    쿼리의 fetching/refetching 여부에 대한 boolean 값.
const {
  isSuccess,
  isError,
  isLoading,
  isFetching,
  data,
  error
} = useQuery(
  'getUsers',
  () => axios.get(`https://jsonplaceholder.typicode.com/users`),
  {
    onSuccess: (data) => {
      console.log('onSuccess', data);
    },
    onError: (error) => {
      console.log('onError', error);
    }
  }
);

if (isFetching) {
  console.log('fetching...');
}

if (isLoading) {
  console.log('loading...');
}

if (isError) {
  console.log('error', error);
}

if (isSuccess) {
  console.log('success', data);
}
const {
  status,
  isFetching,
  data,
  error
} = useQuery(
  'getUsers',
  () => axios.get(`https://jsonplaceholder.typicode.com/users`)
);

if (isFetching) {
  console.log('fetching...');
}

if (status === 'loading') {
  console.log('loading...');
}

if (status === 'error') {
  console.log('error', error);
}

if (status === 'success') {
  console.log('success', data);
}

다음 예제를 통해 useQuery의 사용 방법에 대해 알아보겠습니다. useQuery에 사용한 파라미터는 순서대로 다음과 같습니다.

  • queryKey
    쿼리에 사용할 unique key 값.
  • queryFn
    쿼리에 사용할 promise 기반의 비동기 API 함수.
  • options
    쿼리에 사용할 옵션 값.

 

4-2) useQuery의 Query Key

const {
  status,
  isFetching,
  data,
  error
} = useQuery(
  'getUsers',
  () => axios.get(`https://jsonplaceholder.typicode.com/users`)
);

useQuery에서 파라미터로 사용되는 Query Key는 React Query에서 쿼리 캐싱을 관리하기 위한 unique key로 사용됩니다. 문자열이나 배열로 설정이 가능합니다.

 

Query Key를 문자열로 사용하면 내부적으로 배열로 변환됩니다. 일반적인 목록이나 인덱싱 된 리소스, 비계층적(Non-hierarchical) 리소스를 대상으로 유용하게 사용할 수 있습니다.

 

Query Key를 배열로 사용하는 경우엔 unique key로 사용할 문자열과 serializable 객체를 사용해줍니다. 계층적(Hierarchical) 리소스나 중첩된(nested) 리소스를 대상으로 ID 또는 추가적인 파라미터를 전달하여 사용합니다.

 

5) 실습

const [coins, setCoins] = useState<CoinInterface[]>([]);
const [loading, setLoading] = useState(true);
const getCoins = async () => {
  const res = await axios("https://api.coinpaprika.com/v1/coins");
  setCoins(res.data.slice(0, 100));
  setLoading(false);
};

useEffect(() => {
  getCoins();
}, []);

React Query를 사용하지 않고 일반적으로 비동기로 API를 불러와서 데이터를 저장하는 방식은 위와 같습니다.

 

컴포넌트의 생명 주기를 파악한 후 적절한 시점에 ajax 호출을 하고 서버에서 데이터를 받아오죠.


그리고 useState를 사용할 경우 데이터를 불러와 setState호출을 통해 응답 당시의 server state를 component state로 wrapping 합니다.

 

이렇게 클라이언트 앱은 server state와 client state에 대한 로직 처리를 나누어 선언해주어야 합니다.

 

1. 데이터를 저장할 state(coins)와 데이터가 fetch 되었는지 여부를 확인해주기 위한 state(loading)을 useState 훅으로 선언

2. useEffect 훅을 사용하여 비동기적으로 API를 통해 데이터를 불러오는 함수 실행

3. setState 함수를 사용하여 state를 저장

 

const { isLoading, data } = useQuery<CoinInterface[]>("allCoins", getCoins);

위 3가지 과정을 한 줄의 코드로 간소화 시켜줌과 동시에 캐싱이라는 기능까지 지원해준다는 것을 알 수 있습니다.

 

 

( 출처 : https://freestrokes.tistory.com/170  )

 

React Query 알아보기

React Query 알아보기 React Query의 기본적인 내용에 대해 알아보고 정리한 내용입니다. 1. React Query React Query는 리액트 애플리케이션에서 서버의 데이터를 조회하거나 캐싱, 업데이트, 에러 처리와 같

freestrokes.tistory.com