TanStack Query

정연돈·2025년 12월 27일

이번에 과제로 Tanstack Query에 대하여 공부를 하게 되었다.
내가 배우며 기억에 남는 몇가지를 소개하려 한다.

TanStack Query란

TanStack Query는 서버 상태(Server State) 를 효율적으로 관리하기 위한 라이브러리이다.
여기서 서버 상태란 API 요청을 통해 가져오는 데이터로,
언제 변경될지 알 수 있고 네트워크 상태에 의존한다는 특징이 있다.

TanStack Query를 사용하면 좋은 경우

TanStack Query의 장점을 알기 위해 비교해보자.

1. API로 데이터를 조회하는 경우 (GET 요청)

TanStack Query를 사용하지 않는 경우,
일반적으로 useEffectuseState를 조합하여 데이터를 가져온다.

useEffect(() => {
  setLoading(true);  //로딩
  fetchPosts()
    .then(setPosts)
    .catch(setError)  //에러
    .finally(() => setLoading(false));
}, []);

이 방식에서는

  • 로딩 상태
  • 에러 상태
  • 데이터 상태

를 모두 직접 관리해야 하며,
같은 API 요청이 여러 컴포넌트에서 반복될 경우 중복 코드중복 요청이 발생하기 쉽다.

반면 TanStack Query를 사용하면,

useQuery({
  queryKey: ['posts'],
  queryFn: fetchPosts,
});
  • 로딩(isPending) / 에러(isError) 상태를 자동으로 제공하고
  • 동일한 queryKey에 대해 데이터를 캐싱하여
  • 불필요한 네트워크 요청을 줄일 수 있다.

즉, 데이터를 “어떻게 관리할지”보다 “무엇을 가져올지”에 집중할 수 있다.

2. 동일한 데이터를 여러 페이지에서 사용하는 경우

TanStack Query를 사용하지 않으면 같은 데이터도 페이지가 다르면 다시 요청해야하는 불편함을 가지고 있다.
하지만 TanStack Query를 사용한다면 queryKey에 데이터를 캐싱하여 기존 데이터를 재사용 한다.

이를 통해

  • 페이지 이동 시 깜빡이는 로딩 화면 감소
  • 빠른 화면 전환
  • 네트워크 비용 절감

이라는 장점을 얻을 수 있다.

3. 데이터의 최신성을 제어해야 하는 경우

TanStack Query를 사용하지 않으면 언제 다시 API를 다시 요청해야 하는지 정의하기 어렵다.

하지만 TanStack Query를 사용한다면 staleTime으로 설정 가능하다.

이를 통해

  • 일정 시간 동안은 데이터를 신뢰하고
  • 필요할 때만 refetch하도록 제어할 수 있다.

즉, 데이터의 최신성에 대한 기준을 개발자가 직접 정의 할 수 있다.

Hello, GSM은 TanStack Query를 왜 사용할까

우선 Hello, GSM은 광주 소프트웨어마이스터 고등학교 입학지원 시스템이다.
https://www.hellogsm.kr/
https://github.com/themoment-team/hellogsm-front-25

Hello, GSM이 TanStack Query를 사용한 이유는 API요청 상태관리 때문일 것 같다.

사용자가 직접 데이터를 저장하고, 값을 불러오는 일이 빈번하게 일어난다.
그 때 마다 에러, 로딩 등을 사용자에게 직접 표시 해 주어야하는데 효율적으로 표시하기 위해 사용한다고 생각한다.

Hello, GSM에서 Next.js 사용

import { useMutation } from '@tanstack/react-query';
import type { UseMutationOptions } from '@tanstack/react-query';

import type { AxiosError } from 'axios';

import { memberQueryKeys } from 'client/lib';

import { memberUrl, post } from 'api/libs';

import type { MemberRegisterType } from 'types';

export const usePostMemberRegister = (
  options?: UseMutationOptions<unknown, AxiosError, MemberRegisterType, unknown>,
) =>
  useMutation({
    mutationKey: memberQueryKeys.postMember(),
    mutationFn: (mentorInfo: MemberRegisterType) =>
      post(memberUrl.postMemberRegister(), mentorInfo),
    ...options,
  }); 

해당 코드는 회원가입에 사용되는 커스텀 hook 입니다.
이 훅을 통해 성공/실패 시 동작을 직접 정의할 수 있습니다.

2개의 댓글

comment-user-thumbnail
2025년 12월 27일

즉, 데이터를 “어떻게 관리할지”보다 “무엇을 가져올지”에 집중할 수 있다.

-> 이 부분에 대해서 궁금증이 있는데, 무엇을 가져올지는 typescrpit에 책임이 있고, 어떻게 관리할지 -> 이미 표준화가 된 간단한 방식으로 관리하게 만드는것이 아닐까 싶습니다. 어떻게 생각하시나요?

1개의 답글