[React-Query] 캐싱

스머리·2024년 3월 11일
0

React-Query

목록 보기
4/6

캐시(cache)

유저가 방금 전에 확인한 데이터를 또 보고, 또 보는 경우에도 매번 똑같은 데이터를 백엔드에서 받아온다.. 유저가 자주 보는 데이터를 어딘가에 저장해 두었다가 백엔드에 요청할 필요 없이 바로 보여줄 수 있다. 이럴 때 캐시라는 것을 사용한다.

캐시(Cache)

캐시란 데이터를 미리 복사해 놓는 임시 장소이다. 저장 공간의 크기는 작지만, 데이터를 가져오는 속도는 아주 빠르다는 특징이 있다. 따라서 자주 사용하는 데이터를 캐시에 저장해 두면, 해당 데이터를 빠르게 가져와서 사용할 수 있다.

웹 브라우저는 기본적으로 캐시를 사용해서 속도를 높이고 네트워크 비용을 아낀다. 사이트에 접속했을 때 받아 온 데이터를 캐시 형태로 저장해서, 사용자가 같은 사이트에 접속하면 서버에 매번 데이터를 다시 요청하는 게 아니라 저장해 놓은 데이터를 유저에게 보여준다. 그리고 이렇게 캐시를 사용한 걸 '캐싱'이라고 한다.

React Query의 캐시

리액트 쿼리는 캐싱을 지원한다. 매번 데이터를 백엔드에서 받아 오는 게 아니라, 캐시에 저장되어 있는 데이터를 유저에게 보여주기도 한다. 언제 데에터를 백엔드에서 다시 받아오는 refetch를 하고, 언제 캐시에 저장되어 있는 데이터를 보여 줄까? 우선 리액트 쿼리의 데이터 라이프 사이클을 알아야 한다.

function HomePage() {
  const result = useQuery({ queryKey: ['posts'], queryFn: getPosts });
  console.log(result);

  return <div>홈페이지</div>;
}

컴포넌트가 렌더링되면 useQuery()가 실행되고, 여기서 쿼리 함수로 설정한 getPosts() 함수를 통해 백엔드로부터 포스트 데이터를 받아온다.

useQuery()에서 쿼리 함수 말고도 쿼리 키를 설정해 주었다. 리액트 쿼리 개발자 도구를 열어보면, 현재 캐시에 저장되어 있는 데이터들을 확인할 수 있다.

['posts'] 라는 쿼리 키로 우리가 받아 온 포스트 데이터가 캐시에 저장되어 있다. useQuery()는 먼저 전달받은 쿼리 키로 캐시에 저장된 데이터가 있는지 확인한다. 만약 저장되어 있는 데이터가 없으면 쿼리 함수를 실행해 데이터를 백엔드로부터 받아온다. 그런 다음 쿼리 키(['posts'])로 데이터를 캐시에 저장한다.

useQuery()가 실행 되었는데 이미 ['posts']라는 쿼리 키로 저장된 데이터가 캐시에 있으면 어떻게 될까? 이때는 데이터의 상태에 따라 다르게 동작한다.

데이터 상태에 따라

  • 백엔드에서 이제 막 데이터를 받아와 캐시에 저장된 데이터는 fresh 상태
  • stale time이라고 불리는 특정 시간이 지나면 stale 상태가 됨
  • 컴포넌트가 언마운트되면(DOM트리에서 제거되면) 해당 데이터가 쓰이지 않는 상태가 되어 inactive 상태가 된다.

이미 ['posts']라는 쿼리 키로 저장된 데이터가 있는 경우, useQuery는 캐시에 저장되어 있는 데이터를 리턴한다. 데이터가 fresh 상태라면 캐시에 저장된 데이터를 리턴하고 끝. stale 상태라면 백그라운드에서 refetch를 진행한다. 그리고 백엔드에서 새로 받아 온 데이터로 기존의 ['posts']로 저장되어 있는 데이터를 갱신한다.

데이터가 stale 상태라면 리액트 쿼리는 기본적으로 네 가지 상황에서 refetch를 진행한다. 이를 변경하고 싶다면 각각의 옵션을 변경하면 된다.

  • 새로운 쿼리 인스턴스가 마운트 -> refetchOnMount
  • 브라우저 창에 다시 포커스 -> refetchOnWindowFocus
  • 네트워크가 다시 연결 -> refetchOnReconnect
  • 미리 설정해 둔 refetch interval 시간이 지났을 때 -> refetchInterval

Stale Time

stale time은 얼마만큼의 시간일까? 리액트 쿼리에서는 디폴트 값으로 0이 설정되어 있다. 그래서 모든 데이터는 백엔드에서 막 받아왔어도 stale 상태가 되고, 따라서 매번 데이터가 필요할 때마다 refetch를 하게 된다. 구현하려는 사이트의 특성에 따라 매번 refetch를 할 필요가 없는 상황에서는 stale time 값을 적절히 변경해 주면 된다.

Garbage Collection Time

캐시에 저장된 데이터는 영원히 캐시에 남아있지 않다. 캐시는 한정된 공간이기 때문에 필요 없는 데이터는 삭제해서 다른 데이터가 사용할 수 있는 공간을 마련해줘야 한다. 리액트 쿼리는 필요 없는 데이터를 삭제하는 것도 알아서 해준다. 쿼리 컴포넌트가 언마운트 되어 해당 데이터가 쓰이지 않는 상황이 되면 데이터는 inactive상태가 된다. inactive상태의 데이터는 가비지 컬렉션 타임이 지나면 캐시에서 삭제된다. 이는 기본적으로 5분으로 설정되어 있지만 값을 변경할 수 있다.

라이프 사이클

라이프 사이클 시간 설정

리액트 쿼리에서는 기본적으로 staleTime은 0, gcTime은 5분이다. staleTime이 0이므로 기본적으로는 매번 서버에서 데이터를 다시 받아오게 된다. 그래서 별도의 옵션 값 조정 없이 받아 온 데이터를 리액트 쿼리 개발자 도구로 살펴보면 처음 데이터를 받아 오자마자 데이터가 stale상태가 된다.
이를 변경하려면 useQuery()에서 staleTime 옵션값을 변경해 주면 된다. 아래 코드와 같이 staleTime값을 1분으로 변경하면 처음 데이터를 받아 와도 1분간은 fresh상태로 유지된다. 그러다가 1분이 지마년 stale 상태로 변한다.
마찬가지로 가비지 컬렉션 타임은 gcTime옵션 값을 활용해서 변경할 수 있다.

function HomePage() {
  const result = useQuery({
    queryKey: ['posts'],
    queryFn: getPosts,
    staleTime: 60 * 1000, // 1분
        gcTime: 60 * 1000 * 10, // 10분
  });
  console.log(result);

  return <div>홈페이지</div>;
}

staleTimegcTime은 밀리초(ms)가 기준이기 때문에, 1000이 곧 1초를 의미한다. 위 코드에서는 staleTime이 1분, gcTime이 10분으로 설정된 예시이다.


profile
꾸준히 나아가는 프론트엔드 개발자

0개의 댓글

관련 채용 정보