Bin's Blog

React-Query란?(1편) 본문

React.js

React-Query란?(1편)

hotIce 2023. 9. 11. 16:08
728x90

React-Query 이미지

글의 시작

오늘 다루는 주제는 내가 실제 프로젝트에 적용해봤던 라이브러리이다.

프로젝트에서 급하게 적용하다 보니 제대로 개념을 이해하고 파악하는 시간이 상대적으로 부족했다.

React-Query를 사용해서 얻는 이점이 무엇인지 파악하고, 왜 사용해야 하는지에 대한 물음표를 해소하기 위해서 글을 남기기로 결심했다.

React-Query 내용이 많다 보니 글 하나에 다 담을 수가 없어서 2편으로 나눠서 작성하려고 한다.

오늘은 React-Query의 특징에 대해서 살펴보자.

 

 

 

🤔 React-Query란?

React-Query는 리액트 애플리케이션에서 서버 상태 가져오기, 캐싱, 동기화 및 업데이트를 보다 쉽게 다룰 수 있도록 도와주는 라이브러리이다. 클라이언트 상태와 서버 상태를 명확히 구분하기 위해 만들어졌다.

 

React-Query에서는 기존 상태 관리 라이브러리인 redux, mobX가 클라이언트 상태 작업에 적합하지만, 비동기 또는 상태 작업에는 그다지 좋지 않다고 언급한다. 

 

클라이언트 상태(Client State)와 서버 상태(Server State)는 완전히 다른 개념이며, 클라이언트 상태는 각각의 input 값으로 예를 들 수 있고, 서버 상태는 데이터베이스에 저장되어 있는 데이터로 예를 들 수 있다. 

 

기능

  • 캐싱
  • 동일한 데이터에 대한 중복 요청을 단일 요청으로 통합
  • 백그라운드에서 오래된 데이터 업데이트
  • 데이터가 얼마나 오래되었는지 알 수 있다.
  • 데이터 업데이트를 가능한 빠르게 반영
  • 페이지네이션 및 데이터 지연 로드와 같은 성능 최적화
  • 서버 상태의 메모리 및 가비지 수집 관리
  • 구조 공유를 사용하여 쿼리 결과를 메모화

 

대표적인 특징만 몇 개 보고 지나가자

 

1. 캐싱(Caching)

React-Query의 장점 중 하나는 데이터를 캐싱한다는 점이다. 

캐싱은 자료 보관함을 생각하면 쉽다. 자료 보관함에 데이터를 넣어 놓으면 다음에 또 꺼내서 쓸 수 있고 변동이 있으면 변경해서 보관함에 넣어 놓으면 된다.

 

React-Query는 캐싱을 통해 동일한 데이터에 대한 반복적인 비동기 데이터 호출을 방지하고, 이는 불필요한 API 콜을 줄여 서버에 대한 부하를 줄이는 좋은 결과를 가져온다. 

 

참고로 React-Query에서는 최신의 데이터를 fresh(최신 상태)한 데이터, 기존의 데이터를 stale(최신 상태가 아님)한 데이터라고 한다.

 

데이터 갱신 상황

1.화면을 보고 있을 때

2.페이지의 전환이 일어났을 때

3.페이지 전환 없이 이벤트가 발생해 데이터를 요청할 때 

 

React-Query에서는 기본적인 아래의 옵션들을 제공한다. 

refetchOnWindowFocus, //default: true
refetchOnMount, //default: true
refetchOnReconnect, //default: true
staleTime, //default: 0
cacheTime, //default: 5분 (60 * 5 * 1000)

위의 옵션을 통해서 세 가지 시점에 데이터를 Refetching하는지 파악 가능하다.

 

1.브라우저에 포커스가 들어온 경우(refetchOnWindowFocus)

2.새로운 컴포넌트 마운트가 발생한 경우(refetchOnMount)

3.네트워크 재연결이 발생한 경우(refetchOnReconnect)

 

staleTime과 cacheTime

const { isLoading, isFetching, data, isError, error } = useQuery(
  ["super-hero"],
  getSuperHero,
  {
    cacheTime: 5 * 60 * 1000, // 5분
    staleTime: 1 * 60 * 1000, // 1분
  }
);

staleTime(number | Infinity)

  • staleTime은 데이터가 fresh -> stale 상태로 변경되는 데 걸리는 시간, 만약 staleTime이 3000이면 fresh상태에서 3초 뒤에 stale로 변환
  • fresh 상태일 때는 Refetch trigger(위의 3가지 경우)가 발생해도 Refetch가 일어나지 않는다.
  • 데이터가 한번 fetch 되고 나서 staleTime이 지나지 않았다면(fresh상태) unmount 후 다시 mount 되어도 fetch가 일어나지 않는다. 
  • staleTime의 기본값은 0이기 때문에 일반적으로 fetch 후에 바로 stale이 된다. 

cacheTime(number | Infinity)

  • cacheTime은 데이터가 inactive한 상태일 때 캐싱된 상태로 남아있는 시간이다. 
  • 특정 컴포넌트가 unmount(페이지 전환 등으로 화면에서 사라질 때)되면 사용된 데이터는 inactive한 상태로 바뀌고, 이때 데이터는 cacheTime만큼 유지된다. 
  • cacheTime이 지나면 가비지 콜렉터(메모리 재활용을 위해서 사용됨)로 수집되서 메모리에서 해제된다. 
  • cacheTime이 지나지 않았는데 해당 데이터를 사용하는 컴포넌트가 다시 mount되면, 새로운 데이터를 fetch해오는 동안 캐싱된 데이터를 보여준다.
  • 즉, 캐싱된 데이된 데이터를 계속 보여주는게 아니라 fetch하는 동안 임시로 보여준다. 
  • cacheTime은 staleTIme과 관게없이, 무조건 inactive된 시점을 기준으로 캐시 데이터 삭제를 결정한다.
  • cacheTime의 기본값은 5분이다. 

여기서 주의할 점은 staleTime과 cacheTime의 기본값은 0분과 5분이다. 따라서 staleTime에 어떠한 설정도 하지 않으면 해당 쿼리를 사용하는 컴포넌트(Observe)가 mount됐을 때 매번 다시 API를 요청한다. 

 

staleTime을 cacheTime보다 길게 설정했다고 가정하면, staleTime만큼의 캐싱을 기대했을 때 원하는 결과를 얻지 못할 것이다. 즉, 두 개의 옵션을 적절하게 설정해줘야 한다. 

근데 staleTime이 60분일지라도 유저가 자주 사용하지 않는 데이터라면 굳이 cacheTIme을 60분 이상으로 설정하여 메모리를 낭비할 필요가 없다. 

 

2. Client 데이터와 Server 데이터 간의 분리

프로젝트의 규모가 커지고 관리해야할 데이터가 넘치다 보면, Client에서 관리하는 데이터와 Server에서 관리하는 데이터가 분리될 필요성을 느낀다.

 

Client 데이터: 모달 관련 데이터, 페이지 관련 데이터 등등..

Server 데이터: 사용자 정보, 비동기 API 호출을 통해 불러오는 데이터

 

실제 Client 데이터의 경우 Redux, Recoil, mobX와 같은 전역 상태 관리 라이브러리들을 통해 관리되어오고 있었으나, 문제는 이러한 라이브러리들이 Server 데이터까지도 관리를 해야하는 상황이 발생한다. Client 데이터와 Server 데이터를 완벽히 분리하여 관리에 용이하도록 충분한 기능이 지원된다고 보기 어렵다.

 

그러나 React-Query는 Server데이터를 효율적으로 관리할 수 있다. 아래 코드를 보자.

const { data, isLoading} = useQueries(
    ['unique-key'],
	() => {
        return api({
            url: URL,
            method: 'GET',
        });
    },
    {
        onSuccess: (data) => {
            // data로 이것저것 하는 로직
        }
    },
    {
        onError: (error) => {
            // error로 이것저것 하는 로직
        }
    }
)

 

예시에서는 컴포넌트 내부에서 위와 같은 로직을 통해 Server 데이터를 가져오고 있는데, 이때 onSuccess와 onError 함수를 통해 fetch 성공과 실패에 대한 분기를 간단하게 구현할 수 있다. Server 데이터를 불러오는 과정에서 구현해야 할 추가적인 설정들을 진행할 필요가 없다는 이야기이다. 

 

즉, Client 데이터는 상태 관리 라이브러리가 관리하고, Server 데이터는 React-Query가 관리하는 구조다. 

이를 통해 우리는 Client 데이터와 Server 데이터를 온전하게 분리할 수 있다. 

 

글의 마무리

실제 프로젝트에서 사용했을 때 느꼈던 가장 큰 장점은 데이터를 자동으로 동기화를 해준다는 것이다.

클라이언트 상태와, 서버 상태를 분리해서 작업하니 유지 보수나 가독성적인 측면에서도 크게 향상 되었다.    

728x90

'React.js' 카테고리의 다른 글

Class component vs Functional component  (0) 2023.10.03
React-Query란?(2편)  (0) 2023.09.15
Flux 패턴  (0) 2023.09.01
[React.js] 오늘의 디버깅  (0) 2023.08.01
오늘의 React  (0) 2023.07.14