ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [react-query] stale과 cache의 개념 제대로 이해하기
    Dev/TIL 2022. 9. 5. 19:19
    반응형

    react-query

    https://tanstack.com/query/v4

     

    TanStack Query | React Query, Solid Query, Svelte Query, Vue Query

    Powerful asynchronous state management, server-state utilities and data fetching for TS/JS, React, Solid, Svelte and Vue

    tanstack.com

     

    react query를 통해 서버 상태를 가져오고, 캐시하고, 동기화하고, 업데이트 하는 작업이 수월해질 수 있다.

    • 서버에서 얻은 데이터를 클라이언트 캐시로 저장할 수 있다.
    • 새 데이터를 가져올 때 캐시가 언제 업데이트되는지 등을 관리할 수 있다.

     

    stale과 cache 시간을 조정해주지 않는다면, 캐싱 기능을 제대로 활용할 수 없으니 제대로 알고가는 것이 필요하다.

    Stale time

    • stale: 부실한, 신선하지 않은 → 최신화가 필요한 데이터라고 간주
    • 기본값은 stale(0)
      • 받아오는 즉시 stale하다고 판단하며, 캐싱데이터와 무관하게 계속해서 fetching을 진행
    • 데이터가 fresh -> stale 상태로 변경되는데 걸리는 시간 (캐시된 데이터를 오래된 것으로 간주하는 시간)
    • fresh 상태일때는 쿼리 인스턴스가 새롭게 mount 되어도 네트워크 fetch가 일어나지 않는다.
    • 데이터가 한번 fetch 되고 나서 staleTime이 지나지 않았다면 unmount 후 mount 되어도 fetch가 일어나지 않는다.

     

    stale한 상태가 되면 다음의 경우에 refetch 된다.

    • 새로운 query 인스턴스가 마운트될 때
      (useQuery가 처음 호출될 때, Whenever a new component that calls useQuery mounts, React Query will do a revalidation)
    • 브라우저 화면을 이탈했다가 다시 포커스할 때
    • 네트워크가 다시 연결될 때
    • 특별히 설정한 refetch interval에 의해서 (refetchInterval)

     

    refetchOnWindowFocus 옵션 등으로 기본 refetch 설정을 막을 수 있고

    staleTime 옵션으로 설정한 시간 동안 데이터가 stale 되지 않도록 해 refetch를 막을 수도 있다.

    useQuery(
        [...],
        getData(),
        {
          staleTime: Infinity
          refetchInterval: false,
          refetchOnWindowFocus: false,
          retry: false,
        }
      )
    

     

    Cache time

    • 기본값은 5분 (3000ms)
    • 데이터가 inactive 상태일 때 캐싱된 상태(메모리상에 존재)로 남아있는 시간
    • 쿼리 인스턴스가 unmount 되면 데이터는 inactive 상태로 변경되며, 캐시는 cacheTime만큼 유지된다.
    • cacheTime이 지나면 가비지 콜렉터로 수집된다.
    • cacheTime이 지나기 전에 쿼리 인스턴스가 다시 mount 되면, 데이터를 fetch하는 동안 캐시 데이터를 보여준다.
    • cacheTime은 staleTime과 관계없이, 무조건 inactive 된 시점을 기준으로 캐시 데이터 삭제를 결정한다
    • staleTime: 0일 경우 같은 페이지를 다시 액세스하면 캐시 데이터가 화면에 표시되지만 시간이 지나면 캐시 데이터가 이전 데이터로 간주되므로 백그라운드에서 재추출이 수행

     

    데이터를 리프레시 해야할 때

    • 포스트 요청을 하거나 삭제 요청을 했을 때 화면에 보여주는 데이터에 변화를 줘야 한다.
    • 그러나 query 키가 변하지 않으므로 강제 리프레쉬를 해야할 필요가 있다.
    // Invalidate every query in the cache
    queryClient.invalidateQueries()
    // Invalidate every query with a key that starts with `todos`
    queryClient.invalidateQueries(['todos', 'something'])
    
    queryClient의 invalidateQueries 메소드를 이용해서 query 키를 날려버릴 수도 있다.
    
    
    

    staletime을 지정해주지 않고 쓴다면 react-query의 캐싱 기능을 제대로 활용할 수가 없다.

    따라서 사용은 하긴 해야하나, 만약 데이터 구조가 자주자주 변하는 어플리케이션이라면 지정하지 않는 편이 좋고

    해당 브라우저에 표현되는 내용의 데이터들이 정적이라면 staletime을 지정해주고 요청하는 것이 서버의 부담을 경감시키는 것이 될 것이다.

     

     

    공식 문서에 있는 캐싱 라이프 사이클 참고

     * Query Instances with and without cache data(캐시 데이터가 있거나 없는 쿼리 인스턴스)

    * Background Refetching(백그라운드 다시 페칭)

    * Inactive Queries(비활성 쿼리)

    * Garbage Collection(가비지 컬렉션)

    ---------------------------------------------------------------

    * useQuery('todos', fetchTodos) 마운트 시 새 인스턴스 생성.

    * 이 쿼리 + 변수 조합으로 다른 쿼리가 생성되지 않았으므로이 쿼리는 하드로드 상태를 표시하고 데이터를 가져 오기위한 네트워크 요청을합니다. 그런 다음 해당 캐시의 고유 식별자로 'todos'및 fetchTodos을 사용하여 데이터를 캐시합니다. 후크는 구성된 후 자체를 부실로 표시합니다 staleTime(기본값 0: 또는 즉시).

    * useQuery('todos', fetchTodos)로 두번째 인스턴스 마운트 .

    * 이 정확한 데이터는이 쿼리의 첫 번째 인스턴스에서 캐시에 존재하기 때문에 해당 데이터는 캐시에서 즉시 반환됩니다.

    * 새 인스턴스가 화면에 표시되면, 두 쿼리 (단 하나의 요청 만)에 대해 백그라운드 다시 가져 오기가 트리거됩니다.

    * 가져 오기가 성공하면 두 인스턴스가 새 데이터로 업데이트됩니다.

    * useQuery('todos', fetchTodos)쿼리 의 두 인스턴스가 모두 마운트 해제되어 더 이상 사용되지 않습니다.

    * 이 쿼리에 더 이상 활성 인스턴스가 없기 때문에 쿼리 cacheTime를 삭제하고 가비지 수집하는 데 사용하는 캐시 시간 초과가 설정됩니다 (기본값은 5 분 ).

    * 캐시 제한 시간이 useQuery('todos', fetchTodos)마운트 인스턴스를 완료하기 전에, 쿼리 fetchTodos는 새로운 값으로 쿼리를 채우기 위해 함수가 백그라운드에서 실행되는 동안 사용 가능한 캐시 된 값을 즉시 반환합니다 .

    * useQuery('todos', fetchTodos)로 마운트된 마지막 인스턴스가 해제됩니다.

    * 5 분 이내에 useQuery('todos', fetchTodos) 인스턴스가 더 이상 나타나지 않습니다.

    * 이 쿼리와 해당 데이터는 삭제되고 가비지 수집됩니다.

    반응형
Designed by Tistory.