runky 프로젝트를 진행하면서...
axios로 통신을 구현하다가 통신 최적화와 코드 재활용을 위해 tanstackQuery를 사용하게 되었다.
tanstackQuery에는 기존에 통신했던 값들을 저장해놨다가 사용자가 바로 화면에서 볼 수 있게 하고 뒤에서 통신을 시도해 새로운 값으로 변경하는 기능을 가지고 있다.
이런 기능은 사용자가 통신을 위해 로딩화면 대신 빠르게 값을 볼 수 있다는 점이 UX면에서 좋기 때문이다.
그러기 위해선 tanstackQuery의 staleTime 속성과 gcTime속성을 사용하여 구현할 수 있다.
이때 staleTime 이내에 값이 변경될 경우 사용자는 이전값을 보게 되는 문제가 있다.
이런 문제를 해결하기위해 queryClient.invalidateQueries()를 통해 해당하는 querykey를 가진 통신의 staleTime이 만료된 것으로 친다.
사용자의 닉네임을 예를들면 useUerInfo 훅에 사용자의 staleTime을 5분 gcTime을 10분으로 잡았다.
export const useUserInfo = () => {
return useQuery<UserInfo>({
queryKey: queryKeys.member.info(),
queryFn: getUserInfo,
gcTime: 10 * 60 * 1000,
staleTime: 5 * 60 * 1000
});
};
이후 사용자가 닉네임을 변경하는 통신을 하게 된다면 get통신의 쿼리키를 사용하여 해당 통신의 staleTime을 만료 시킨다.
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { updateNickname } from '@/utils/apis/member';
import { useState } from 'react';
import { queryKeys } from '@/utils/queries/queryKeys';
export const useSetNickname = () => {
const queryClient = useQueryClient();
const mutation = useMutation({
updateNickname,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: queryKeys.member.info() });
//통신 성공시 멤버 get 통신의 staleTime을 만료시킨다.
//통신 추가 처리
},
onError: (error: unknown) => {
//...에러처리
}
});
return { ...mutation };
};
해당 기능을 프로젝트에 적용하여 유저정보,재화,아이템, 주간 러닝 목표의 staleTime과 gcTime을 설정하여 통신 호출양을 줄이고 최적화 하였다.
각각 크롬 시크릿 모드에서 3번씩 테스트를 진행하였다.


| 측정 항목 | 캐시 적용 전 | 캐시 적용 후 | 개선 효과 |
|---|---|---|---|
| API 호출 횟수 | 7 회 | 2 회 | 약 71.4% 감소 |
| API 호출 시간 | 약 156 ms | 약 114 ms | 약 27% 단축 |
이번 최적화 경험을 통해 tanstackQuery의 캐싱 기능이 api 호출과 서버의 부담을 줄이고 사용자에게 끊김없는 경험을 제공하는 효과적인 기능이라고 느꼈다.
또한 통신 데이터의 특성에 맞게 staleTime과 gcTime을 적당하게 설정하는 것이 어려우면서 중요한것 같다.