Cache-time, Stale-time
나는 처음에 리액트 쿼리가 서버에 첫 번째 요청 이후 응답 값을 데이터를 캐시에 저장하는데, 만약 같은 요청을 다시 하고, 응답 값이 캐시에 저장되어 있다면 서버에 요청을 보내지 않고 캐시에 저장된 데이터를 불러오는 라이브러리인 줄 알았다. 근데 이 부분은 조금 틀렸다는 사실을 얼마 전에 알게 되었다.
리액트 쿼리의 Cache-time, Stale-time의 기본 설정은 Cache-time이 5분, Stale-time은 0초이다. 이는 캐시에 데이터가 5분간 저장된다는 것을 의미하는데, 저장된다고 해서 같은 데이터를 요청했을 때 서버에 요청을 보내지 않는 것은 아니었다. 이유는 Stale-time이 0초이기 때문인데, 이는 캐시에 저장된 데이터가 신선하다고 판단하는 시간이 0초라는 의미이며, 이는 신선하지 않기 때문에 서버에 요청을 보내서 확인을 하는 작업이 필요하다는 것을 의미한다.
이는 즉, 5분간 캐시에 데이터를 저장하되, 저장된 데이터는 신선하지 않기 때문에 서버에 요청을 보내 데이터가 신선한지 확인을 한 이후, 신선하다면 캐시에 저장된 데이터를 가져오고, 신선하지 않다면 바뀐 부분을 추가해서 데이터를 가져오는 것을 의미한다. 결국 stale-time이 0초면 일단 서버에 요청을 무조건 보내야 한다는 것을 의미한다. 따라서 웹 애플리케이션의 성능을 높이기 위해선 상황에 맞는 Cache-time, Stale-time을 설정하는 것이 중요하다.
Cache-time, Stale-time 설정하기
Cache-time, Stale-time을 설정하는 방법은 간단하다. QueryClient를 설정할 때 아래와 같이 옵션을 넣어주면 된다.
// app.js
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5분 (밀리초 단위)
cacheTime: 24 * 60 * 60 * 1000, // 24시간 (밀리초 단위)
},
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
<Components/>
</QueryClientProvider>
);
}
전체가 아니라 개별적인 쿼리를 사용할 때도 유사하게 사용하는데, 코드는 아래와 같다.
const { data } = useQuery('someKey', fetchDataFunction, {
staleTime: 10000, // 10초
cacheTime: 60000, // 1분
});
이러한 설정을 통해 사용자 경험과, 성능을 향상시킬 수 있으며 상황에 맞는 적 잘한 Cache-time, Stale-time을 설정하는 것은 중요하다.
프로젝트에서 구현
중고 의류 거래 플랫폼 프로젝트를 진행하면서 생긴 문제점이 있었다. 중고 거래를 위한 플랫폼이기 때문에 누구나 판매자가 되고, 구매자가 될 수 있는데 사용자가 판매자냐, 구매자냐에 따라 버튼의 유무나 상점 페이지에서 보여줘야 할 요소가 다르다는 점이었다. 이 점들은 유저의 id 값을 기반으로 구분 짓는 로직을 가지고 있었고, 이에 따라 여러 컴포넌트에서 동일한 요청을 반복하는 문제가 있었다. 유저의 id는 변경되지 않기 때문에 지속적으로 서버에 요청하는 것은 불필요한 요청이라고 생각했고, Cache-time, Stale-time을 infinity로 설정해 캐싱된 데이터를 사용할 수 있도록 했다.
쿼리 설정 코드
const { data: category } = useQuery('category', getCategory, { staleTime: Infinity, cacheTime: Infinity });
위와 같이 설정을 해서 서버에 요청을 하지 않도록 설정을 했다. 여기서 새로운 문제가 발생을 했는데, 유저의 id를 가져오는 GET 요청은 유저의 프로필 이미지, 상점명 등 다른 데이터도 같이 가져올 수 있도록 구성이 되어있었고, 위와 같은 코드를 사용했을 때, 유저의 상점명이나 프로필 이미지가 바뀌었을 경우에도 새로운 데이터를 불러오지 않고 캐싱된 데이터를 불러오기 때문에 웹 페이지 상에 변경된 데이터가 적용이 안되었다. 따라서 프로필 이미지와 상점명과 같은 유저의 정보가 변경이 되었을 경우 쿼리를 초기화시키는 방법을 사용해서 문제를 해결하였다.
const mutation = useMutation(changeImages, {
onSuccess: () => {
queryClient.invalidateQueries('profileImage');
queryClient.invalidateQueries('myInfo'); // 유저 정보 쿼리를 초기화 하는 부분
},
});
'React' 카테고리의 다른 글
useMemo를 사용한 성능 최적화 (1) | 2023.11.27 |
---|---|
SSE 실시간 알림 기능 구현 (0) | 2023.11.20 |
이미지 최적화(Browser image Compression) (0) | 2023.11.20 |
React lazy, Suspense (2) | 2023.11.20 |
React memo (1) | 2023.11.20 |