Caching with React Query

김윤진·2022년 11월 9일
1

우아한테크코스

목록 보기
6/8

레벨로그 프로젝트

React Query Cache


리액트 쿼리는 개발자에게 캐시 설정을 쉽게 할 수 있는 옵션을 제공한다.
바로 cacheTimestaleTime

쿼리 상태

  • fetching : 요청 중인 쿼리

  • fresh : 새롭게 추가된 쿼리 (만료되지 않아, 컴포넌트가 마운트/업데이트 되어도 데이터를 재요청하지 않는다.)

  • stale : 만료된 쿼리 (만료되었기 때문에, 컴포넌트가 마운트/업데이트 되면 데이터를 재요청한다.)

  • inactive : 비활성화된 쿼리 (사용되지 않는 쿼리로, 일정 시간이 지나면 가비지 컬렉터가 캐시에서 제거한다.)

캐시 옵션

  • cacheTime

    • inactive 상태일 때 메모리에 캐시를 언제까지 유지할 지에 관한 시간

    • 메모리에 저장된 캐시 데이터가 언제까지 유지될지 알려주는 옵션 (default = 5분)

  • staleTime

    • fresh -> stale까지의 시간

    • 데이터의 신선한 상태가 언제까지 지속될지에 관한 시간 (default = 0)


리액트 쿼리는 데이터를 패칭한 후 응답받은 데이터를 캐시 메모리에 캐시한다.

cacheTime은 이 캐시된 데이터를 저장하는 시간을 지정할 수 있다.

만약 cacheTime에 설정한 시간이 경과되면 가비지 컬렉터의 가비지 컬렉팅 대상이 된다. 그리고 cacaheTime이 경과되기 전에 재요청을 보낸다면 요청이 가는 것이 아닌 캐시되어 있는 데이터를 응답하여 불필요한 통신에 대한 리소스 절약을 도모할 수 있다는 장점이 있다.

staleTime은 캐시된 데이터에 대한 제검증에 대한 시간을 지정할 수 있다.

staleTime에 지정한 시간이 경과되면 요청을 보내 서버의 상태를 가져와 캐시 데이터를 최신화한다.

이런 캐시 설정은 객관적인 데이터를 기반으로 설정해야 한다. 사용자의 행동을 기반으로 사용자 경험이 떨어지지 않고 네트워크 비용을 최소화 해야 하기 때문이다.
하지만 레벨로그 프로젝트에서는 이런 객관적인 데이터를 제공하는 직군이 존재하지 않기에 사용자 입장에서 생각해보고 결과를 도출하였다.

  • cacaheTime 0 설정 : 인터뷰 팀 상세 페이지, 레벨로그 수정 페이지, 사전질문 수정 페이지

    • 인터뷰 팀 상세 페이지에서 cache된 데이터를 띄워주고 재검증을 통해 변경된 데이터를 변경하면 사용성에 좋지 않다라고 생각함. 왜냐하면 재검증하는 순간동안 사용자는 콘텐츠가 존재하지 않는다고 인지하고 이탈할 수 있는 가능성이 있기 때문
  • staleTime 60 설정 : 받은 피드백들 보여주는 페이지, 받은 인터뷰 질문들 보여주는 페이지

    • 재검증해야하는 빈도가 낮다고 생각함, 왜냐하면 인터뷰가 종료하고 보는 컨텐츠이기 때문

    • 대신 피드백이나 인터뷰 질문 작성시 invalidateQueries 를 통해 캐시 재검증하도록

  • staleTime 600 설정 : 인터뷰 검색 결과 페이지

    • 재검증해야하는 빈도가 많이 낮다고 생각함. 왜냐하면 불특정 다수의 데이터가 들어가있고 키워드 검색이 주 라고 생각함, 어떤 한 질문에 종속된 것이 아니라고 생각함

또한 이 cacheTimestaleTime을 쿼리마다 다르게 지정할 수 있다는 장점도 존재한다. 하지만 useQuery를 통해 응답받은 데이터만 가능하다. 왜냐하면 get 요청으로 응답 받은 데이터를 제외한 post, delete, put 요청은 캐시를 하는 비용이 더 크다고 리액트 쿼리에서 판단했기 때문이다.



Web Cache


브라우저는 자체적인 캐시 타임을 가지고 있다. 이것을 휴리스틱 캐시라고 하는데 이는 동일한 사용자 경험을 제공하는 것에 좋지 않다. 이로 인해 웹 캐시 설정을 하는 것이 네트워크 비용 절약 뿐만 아니라 동일한 사용자 경험을 제공할 수도 있다.

cache control

  • max-age

    • 데이터를 캐시하는 최대 시간을 지정할 수 있다.

    • 해당 시간이 경과되지 않으면 리소스를 캐시 메모리에서 응답한다.

    • 브라우저에 저장된 캐시는 사용자가 직접 지우지 않는 이상 개발자가 조절할 수 없다.

    • 그래서 최신 리소스를 바라보게 하기 위해 번들링할 때 content hash를 지정해서 파일명이 다르다는 것을 인지시킬 수 있다.

레벨로그 서비스에서는

  • HTML 파일은 max-age = 0

    • HTML 파일은 항상 재검증을 한다.

    • 레벨로그 서비스는 SPA, CSR 방식으로 이 HTML 파일이 가볍다는 점이 존재한다.

    • 그래서 HTML 파일 재검증을 통해 HTML 파일의 script 태그(js 파일)의 파일명(content-hash)이 변경 되었다면 해당하는 js 파일도 재검증하는 과정을 거친다.

  • 다른 정적 리소스(js, image, font등)는 max-age = 1년

    • 용량이 비교적 큰 js, image, font 는 재검증하는 빈도를 최소화하기 위해 max age를 길게 잡는 것이 좋다.
  • no-cache

    • no-cache는 max-age=0과 동일하게 동작한다. 캐시는 저장하지만 사용하려고 할 때마다 서버에 재검증 요청을 보낸다.
  • no-store

    • no-store는 캐시를 절대로 해서는 안 되는 리소스일 때 사용한다. 브라우저의 어떤 캐시 저장소라도 해당 리소스를 저장하지 않는다.

이 둘의 차이는 일부 모바일 브라우저의 경우 브라우저를 종료하기전까지 리소스가 만료되지 않는 경우가 있어 모든 브라우저에서 동일한 사용자 경험을 제공하기 위해서는 no-store를 사용하는 것이 좋는 것이 좋다.

CDN과 같은 중간 서버가 리소스를 캐시할 수 있는지 여부를 결정할 수 있는 설정이 존재한다. public, private

  • public

    • 브라우저와 중간 서버가 캐시를 저장할 수 있음을 의미한다.
  • private

    • 중간 서버인 CDN에만 캐시를 저장기간을 지정할 수 있다.
  • s-maxage

    • s-maxage를 통해 중간 서버의 캐시 time을 설정할 수 있다.


Browser Cache


브라우저 캐시에는 메모리 캐시와 디스크 캐시가 존재한다.

  • memory cache

    • memory cache는 더 빨리 캐시를 가져오기 위해서 캐시 메모리에서 가져온다. 캐시 메모리에는 L1, L2, L3 가 있고 보통 CPU에 내장되어 있다. 캐시 메모리는 브라우저를 닫으면 캐시가 지워진다. CPU에 내장되어 있기에 캐시를 빨리 가져올 수 있는 것이다.
  • disk cache

    • disk cache는 큰 용량을 저장하기 위해서 하드디스크, SSD에서 가져온다. 디스크 캐시는 브라우저를 닫더라도 캐시는 지워지지 않는다.

캐시 메모리와 디스크 캐시에 저장되는 기준은 제가 찾아본 결과 리소스 용량이라고 추정한다. 캐시 메모리는 8KB에서 8MB로 작은 용량이 이므로 그 이상의 리소스인 경우에는 디스크 캐시에 저장된다.

0개의 댓글