stale-while-revalidate는 확장 Cache-Control
디렉티브이다. (Cache-Control
은 HTTP 요청과 응답에서 사용되는 헤더의 일종으로, 캐싱 메커니즘을 위해 사용된다.)
캐시된 컨텐츠를 즉시 로드하는 즉시성과 업데이트 된 캐시 컨텐츠가 향후에 사용되도록 하는 최신성을 보장하는 데 도움을 준다. stale-while-revalidate는 비동기적으로 컨텐츠를 재검증하는 동안 클라이언트가 stale한(=최신이 아닌) 응답을 받을 것임을 나타낸다.
Cache-Control: max-age=1, stale-while-revalidate=59
React Query는 이러한 stale-while-revalidate 전략을 채택한 비동기 상태 관리자이다. 즉, React Query는 데이터를 캐싱하고 요청 시 데이터가 stale하더라도 데이터를 반환한다.
기존
수정 후
invalidateQueries
메서드 사용App.tsx
에서 QueryClient
를 이용하여 전역 에러 처리API 요청은 문제 없이 동작하는데 invalidateQueries
가 동작하지 않는 문제가 있었다. 코드는 아래와 같았다.
응답으로 받아온 data에 id가 제대로 들어오지 않는 건가? 라는 생각에 onSuccess 콜백 함수를 async/await로 수정해보았다. 하지만 문제가 해결되지 않았다.
Query Key가 잘못된 게 아니라면 queryClient가 문젠가 싶어서 다른 사람들의 코드와 공식 문서 예시를 찾아보았다. 찾아보니 new QueryClient()
가 아니라 useQueryClient()
를 사용해야 함을 발견했다.
React Query는 동일한 QueryClientProvider에 있는 경우 동일한 데이터를 가져오고, 동시에 발생하는 요청의 중복을 제거하므로 위의 시나리오에서는 두 컴포넌트가 동일한 데이터를 요청하더라도 네트워크 요청은 하나만 있습니다.
[번역] #10: 리액트 쿼리는 상태 관리자다
queryClient에 대해 잘 알지 못해서 원인을 찾는 데에 시간이 걸렸다. 동일한 queryClient가 아니었기 때문에 invalidate할 해당 쿼리가 존재하지 않아서 생긴 문제인 것 같다. 좀 더 알아봐야겠다..!
App.tsx
에서 아래와 같이 queryClient에서 QueryCache를 만들어 OnError 옵션에 대해 콜백 함수를 작성했다. 그런데 몇 몇 API 요청 시 에러가 발생해도 toast가 보이지 않는 문제가 있었다.
모든 API 요청에서 발생한 문제가 아니라 로그인, todo 수정&삭제에서 발생한 문제였다. 코드를 확인해보니 해당 동작의 커스텀 훅을 사용할 때 다른 옵션을 주었기 때문에 옵션이 덮어씌워져서 동작하지 않는 게 아닐까?라고 생각했다.
그래서 옵션을 지우고 다시 확인해보았으나 문제는 해결되지 않았다. 그래서 처음에 전역 에러 처리를 할 때 참고했던 TkDodo의 글에서 'overwrite'를 검색해서 아래와 같은 댓글을 발견했다.
그런데 전역 에러 처리를 하려면 QueryCache나 MutationCache를 사용하라고 적혀있는 것을 보고 MutationCache를 작성하지 않은 게 문제였음을 깨달았다. 그리고 코드를 아래와 같이 수정했고, 문제 없이 잘 동작하는 것을 확인했다!
지난 번에 개인 토이 프로젝트를 할 때에도 React Query를 사용해보려고 했으나, 급한 마음으로 슥 훑어보고는 '어렵다.. 다음에 해 봐야지' 하고 생각했었다. 그런데 어려워도 일단 써봐야 어떻게 하는 건지 조금이라도 감이 오고 결국 사용할 수 있게 되는 것 같다.
공식문서와 여러 포스팅을 읽고 React Query를 사용해보면서 그동안 API 요청에 대해 꼼꼼히 모든 경우를 처리한 적이 없음을 깨달았다. 그리고 관련 코드를 작성할 때 필요한 부분이라는 이유로 코드 품질을 떨어뜨리고 있지는 않았는지 반성하게 되었다. 부족한 나를 도와줄 수 있는 알맞는 도구를 선택하는 것도 중요하겠다는 생각을 했다.
내가 느낀 React Query의 장점은 서버 데이터 관리 로직을 React Query에서 처리함으로써 코드가 간결해지고 서버 데이터를 관리하는 게 편리해졌다는 것이다. 그래서 서버에서 데이터를 가져오는 작업이 많은 앱일 경우 React Query를 사용하는 게 훨씬 좋을 듯하다. React Query에 대한 글을 읽으면서 SWR이 같이 언급되는 경우가 종종 있었는데 둘의 차이점은 무엇인지도 한 번 알아봐야겠다.
참고한 글