[TanstackQuery] 캐시, Cache

강연주·2024년 12월 9일

 🏝️ TanstackQuery

목록 보기
3/7

캐시 (Cache)

백엔드에서 데이터를 가져오는 일은 내 컴퓨터에 있는 데이터를 가져오기보다 시간이 오래 걸린다. 그런데 유저가 방금 확인한 데이터를 보고 또 보고 반복해서 보는 경우, 매번 데이터를 백엔드에서 받아오는 수고를 덜기 위해 이 데이터를 백엔드 요청 대신 어딘가에 저장해두었다가 바로 보여주면 된다.

캐시란, 데이터를 미리 복사해놓는 임시 장소. 보통 저장 공간의 크기는 작지만 데이터를 가져오는 속도는 빠르다는 특징이 있어, 자주 사용하는 데이터를 캐시에 저장해두면 효율적이다.

웹 브라우저는 기본적으로 캐시를 사용해 속도를 향상시키고 네트워크 비용을 절감하고, 이렇게 캐시를 사용하는 것을 '캐싱'이라고 한다.

Tanstack Query의 캐시

탠스택쿼리 역시 캐싱을 지원한다. 매번 백엔드에 요청을 하는 대신 캐시에 저장된 데이터를 유저에게 보여주기도 하는 것인데, 그렇다면 언제 refetch로 백엔드 데이터를 다시 받아오고 언제 캐시의 데이터를 보보여줄까? 이를 이해하기 위해 우선 탠스택 쿼리의 데이터 라이프 사이클을 알아야 한다.

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

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

Hompage라는 컴포넌트가 렌더링되면, useQuery()가 실행되고, 여기서 쿼리 함수로 설정한 getPosts() 함수를 통해 백엔드로부터 포스트 데이터를 받아온다. 그런데 useQuery()를 사용한다고 무조건 쿼리 함수가 실행되어 백엔드 데이터를 받아오는 것은 아니다.

useQuery()에는 쿼리 함수 외에 쿼리키 또한 설정되어 있다. 탠스택 쿼리 개발자 도구를 열어보면 현재 캐시에 저장되어 있는 데이터들을 확인할 수 있고, ['posts']라는 쿼리 키로 받아온 포스트 데이터도 캐시에 저장돼있다.

만약 useQuery()이 실행됐는데, 이미 ['posts']라는 쿼리 키로 저장된 데이터가 캐시에 존재하면 어떻게 될까? 이때는 데이터의 상태에 따라 다르게 동작한다. 탠스택 쿼리는 방금 막 받아온 데이터는 fresh 즉, 신선한 상태로 판단한다. 그러다가 stale time이라고 불리는 특정 시간이 경과하면 데이터는 stale 즉, 신선하지 않은 상태가 된다. 마지막으로 컴포넌트가 언마운트되면(DOM 트리에서 제거되면) 해당 데이터가 쓰이지 않아 inactive 상태가 된다.

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

데이터가 stale 상태라면 리액트는 기본적으로 다음 네 가지 상황에서 refetch를 진행하는데,

  1. 새로운 쿼리 인스턴스가 마운트 되거나 (refetchOnMount)
  2. 브라우저 창에 다시 포커스가 가거나 (refetchOnWindowFocus)
  3. 네트워크가 다시 연결되거나 (refetchOnReconnect)
  4. 미리 설정해둔 refetch interval 시간이 지났을 때 (refetchInterval)

refetch를 진행한다. 이를 변경하고 싶다면 각각 refetchOnMount, refetchOnWindowFocus, refetchOnReconnect, refetchInterval 옵션을 변경하면 된다.

Stale Time

탠스택 쿼리의 stale time 기본값은 0으로 설정되어 있어서, 사실상 모든 데이터는 받아오자마자 바로 stale 상태가 되고 필요할 때마다 refetch를 진행한다. 사이트의 특성에 따라 stale time을 적절히 변경해주도록 한다.

Garbage Collection Time

이렇게 캐시에 저장된 데이터는 영원히 남아있을까? 캐시는 한정된 공간이기 때문에 필요없는 데이터는 삭제해서 다른 데이터가 사용하도록 공간을 마련해줘야 한다. 탠스택쿼리는 불필요한 데이터 삭제도 알아서 처리해준다. 쿼리 컴포넌트가 언마운트 되어 해당 데이터가 쓰이지 않는 상황이면 데이터가 inactive 상태가 된다고 했는데, inactive 상태의 데이터는 가비지 걸렉션 타임이 지나면 캐시에서 삭제된다. 기본으로 5분으로 설정되어 있고 이 값 역시 변경 가능하다.


라이프 사이클

  1. useQuery()가 실행 컴포넌트가 마운트되면 useQuery()를 통해 쿼리 함수가 실행되고 데이터를 받아온다.
  2. 받아 온 데이터는 useQuery()에서 지정해 줬던 쿼리 키를 이용해 캐싱, 즉 캐시에 저장된다.
  3. 캐시에 저장된 데이터는 fresh 상태에서 staleTime이 지나면 stale 상태로 변경된다
  4. 유저가 데이터를 요청하면 캐시 데이터를 먼저 보여주는데
    4-1. 이때 데이터가 fresh 상태면 추가적인 refetch를 진행하지 않고
    4-2. stale 상태면 백그라운드에서(자체적으로 알아서) refetch를 진행한다.
  5. refetch가 끝나면 새로운 데이터로 유저에게 보여준다.
  6. 컴포넌트가 언마운트되어서 데이터가 inactive 상태가 되면 gcTime(가비지 컬렉션 타임) 동안 캐시에 저장되어 있다가 그 이후에 가비지 콜렉터에 의해 삭제가 되면서 여정이 마무리된다.

라이프 사이클 시간 설정

탠스택 쿼리의 기본 staleTime은 0, gcTime은 5분.
staleTime이 0이므로, 매번 서버 데이터를 받아오고, 별도 조정 없이 받아온 데이터를 탠스택 쿼리 개발자 도구로 확인해보면 데이터가 바로 stale 상태가 되는 것을 볼 수 있다. 아래 코드처럼 staleTime과 gcTime을 설정할 수 있다.

function Homepage() {
	const result = useQuery({
    	queryKey: ['posts'],
        queryFn: [getPosts],
        staleTime: 60 * 1000,
        	gcTime: 60 * 1000 * 10,
    });
    
    console.log(result);
    
    return <div>홈페이지</div>
}
 

staleTime과 gcTimed은 밀리초(ms) 기준이므로, 1000이 곧 1초를 의미한다.

출처 : 코드잇 React Query

profile
아무튼, 개발자

0개의 댓글