카테고리 없음

TanStack Query는 서버 상태를 어떻게 관리할까?

핢이 2025. 3. 28. 12:53

1. TanStack Query의 핵심 개념

TanStack Query는 서버 상태를 관리하기 위해 Query와 Mutation이라는 두 가지 개념을 사용한다.

  • Query: 서버에서 데이터를 가져오는 역할 (useQuery 사용)
  • Mutation: 데이터를 변경하는 역할 (useMutation 사용)

이를 활용해 서버와 클라이언트 간의 상태를 일관성 있게 유지할 수 있다.

또한, Query Key라는 개념을 통해 데이터를 구분하고 관리한다.

Query Key는 특정 데이터를 식별하는 고유한 키이며, 동일한 Query Key를 가진 데이터는 캐싱되어 효율적으로 관리된다.


2. TanStack Query의 내부 동작 원리

1) 요청 및 응답 흐름

TanStack Query의 useQuery가 실행되면 다음과 같은 과정이 진행된다.

  1. Query Key를 기반으로 캐시 확인 → 동일한 요청이 이미 캐시에 있다면, 캐시된 데이터를 반환
  2. 캐시에 없는 경우, Fetch 요청 실행 → 서버에서 데이터를 가져옴
  3. 응답 데이터 캐싱 → 가져온 데이터를 Query Cache에 저장
  4. Stale Time을 기준으로 데이터 상태 관리 → 일정 시간이 지나면 데이터가 자동으로 갱신됨
const { data, isLoading, error } = useQuery(['user', userId], () => fetchUser(userId));

 

위 코드에서 ['user', userId]는 Query Key로, 같은 Key를 가진 요청은 중복되지 않고 캐시에서 처리된다.


2) 캐싱과 데이터 저장 방식

TanStack Query는 내부적으로 Query Cache라는 저장소를 사용해 데이터를 보관한다.

기본적으로 다음과 같은 캐싱 전략을 따른다.

  • Stale Time: 데이터가 신선한 상태를 유지하는 시간 (기본값: 0초 → 즉시 만료)
  • Cache Time: 사용되지 않는 데이터를 메모리에 유지하는 시간 (기본값: 5분)

이를 통해 불필요한 네트워크 요청을 방지하고, 데이터의 최신성을 유지할 수 있다.

const { data } = useQuery(['posts'], fetchPosts, { staleTime: 10000, cacheTime: 600000 });

 

위 코드에서는 10초 동안 데이터가 신선한 상태(Stale Time)로 유지되며, 사용되지 않더라도 10분 동안(Cache Time) 캐시에 남아있게 설정했다.

 

✍🏻캐시된 데이터를 언제 갱신할까?

  • invalidateQueries를 사용하면 필요할 때 강제로 데이터 새로고침이 가능하다.
const queryClient = useQueryClient();
queryClient.invalidateQueries(['posts']); // 서버에서 다시 가져옴
  • refetchOnWindowFocus: false 설정하면 다시 창을 활성화할 때 자동 갱신되지 않는다.
useQuery(['posts'], fetchPosts, {
  refetchOnWindowFocus: false,
});
  • staleTime을 설정하면, 해당 시간이 지나기 전까지는 항상 캐시 데이터를 사용한다.
useQuery(['posts'], fetchPosts, {
  staleTime: 1000 * 60 * 5, // 5분 동안은 캐시 데이터만 사용
});

 

 


3) 데이터 동기화 및 자동 리페칭

TanStack Query는 사용자의 행동에 따라 자동으로 데이터를 동기화한다.

  • Window Focus 시 리페칭: 사용자가 브라우저 탭을 다시 열면 최신 데이터 자동 요청
  • 네트워크 복구 시 리페칭: 오프라인 상태였다가 다시 연결되면 최신 데이터 요청
  • Refetch 옵션: 특정 이벤트(ex 버튼 클릭)에서 refetch를 호출하여 데이터를 갱신 가능
const { data, refetch } = useQuery(['profile'], fetchProfile, { refetchOnWindowFocus: true });
<button onClick={() => refetch()}>다시 불러오기</button>

4) 중복 요청 방지 및 배치 처리

TanStack Query는 동일한 Query Key를 가진 중복 요청을 자동으로 방지한다. 또한, 여러 개의 Mutation을 배치 처리(batch processing)하여 성능을 최적화할 수 있다.

const mutation = useMutation(updateUser, {
  onMutate: (newData) => {
    queryClient.setQueryData(['user', newData.id], newData);
  }
});

이렇게 하면 네트워크 요청을 보내기 전에 로컬 상태를 먼저 업데이트하여 빠른 응답성을 제공할 수 있다.


5) 오프라인 지원 및 백그라운드 동기화

기본적으로 캐시는 브라우저가 닫히거나 새로고침하면 사라진다. 하지만, TanStack Query는 persistQueryClient 기능을 제공하여 오프라인 환경에서도 데이터를 유지할 수 있다. 네트워크가 복구되면 자동으로 최신 데이터를 동기화하는 기능도 포함되어 있다.

persistQueryClient({ queryClient, storage: window.localStorage });

 

이 기능을 사용하면 네트워크가 끊겨도 (브라우저 창을 닫아도) 이전 데이터를 유지하면서, 연결이 복구될 때 자동으로 최신 데이터를 요청할 수 있다.


3. TanStack Query가 제공하는 이점

✅ TanStack Query의 주요 장점

  • 자동 캐싱 및 중복 요청 방지 → 불필요한 네트워크 요청 최소화
  • Stale Time, Cache Time을 통한 유연한 데이터 관리 → 성능 최적화
  • 자동 동기화 및 백그라운드 데이터 갱신 → 항상 최신 데이터 유지
  • 오프라인 지원 및 오류 복구 기능 → 사용자 경험 개선

🔥 기존 방식 대비 차이점

과거에는 Redux, Context API 등을 사용해 서버 상태를 직접 관리해야 했지만, TanStack Query는 이를 자동화하여 개발자의 부담을 줄인다. Redux와 비교하면, TanStack Query는 비즈니스 로직 없이 API 호출만으로 상태를 관리할 수 있어 코드가 간결하다는 장점이 있다.