useQuery를 이용해 비동기데이터 관리하기

white noise·2025년 11월 10일

스터디를 하면서 useQuery를 이용해 상태관리 하는 법을 배웠다. 하지만 얼레벌레 과제를 하다 보니 useQuery를 제대로 모르는 것 같아서 한번 알아보려고 한다.

Query란?

일단 쿼리(Query)란 무엇일까?

쿼리.. 많이 들어봤는데 뭔지 잘 모르겠어서 찾아봤다.
query란 '질문하다'라는 뜻을 가지고 있으며, 프로그래밍에서는 데이터베이스에 원하는 정보를 요청하고 추출하기 위한 질문이나 명령이라고 한다.

useQuery에 대해 알아보자

그럼 제목인 useQuery는 뭔데 비동기 데이터를 관리할 수 있는걸까?

일단 useStateuseEffect를 사용해서 비동기데이터를 관리할 때를 생각해보자.

useState를 이용해서 비동기 데이터도 받아줘야하고.. useEffect로 비동기 함수를 실행하고 데이터를 의존성 배열에도 넣어줘야 하고...

const [data, setData] = useState<ResponseMyInfoDto>([]);

  useEffect(() => {
    const getData = async () => {
      const response = await getMyInfo();
      console.log(response);

      setData(response);
    };

    getData();
  }, []);

대충 이런 형식이 나올 것이다.
근데 사실 이게 다가 아니라 Loading일 때, Error일 때 등을 위해 useState를 또 선언해줘야한다.

관리가 정말 귀찮다..

이럴때 사용하는게 useQuery이다.

useQuery 사용법

구 React Query, 현 TanStack Query는 서버의 상태를 불러오고, 캐싱하며, 지속적으로 동기화하고 업데이트 하는 작업을 도와주는 라이브러리이다.

일단 설치하고 시작하자

npm i @tanstack/react-query

pnpm add @tanstack/react-query

yarn add @tanstack/react-query

그리고선 QueryClientProvider를 최상단에 감싸줘야 한다.

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();
export function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <WelcomeData />
    </QueryClientProvider>
  );
}

이런식으로 감싸주면 된다.

{ data, isPending, isError } = useQuery({
    queryKey: [QUERY_KEY.lps, lpId],
    queryFn: () =>
      getLpDetail({
        lpId,
      }),
});
  • queryKey [QUERY_KEY.lps, lpId]를 Key로 사용하여 이 Unique Ket로 서버 상태를 로컬에 캐시하고 관리한다.
  • queryFn으로 비동기 함수를 등록한다. 이 함수를 통해 데이터를 받아올 수 있다.
  • { data, isPending, isError } 과 같은 상태를 받아올 수 있어서 useState를 이용한 상태관리를 직접 안해줘도 된다!

많이 사용하는 쿼리 옵션들

  • enabled(boolean): 쿼리가 자동으로 실행되지 않게 설정하는 옵션
  • retry(boolean | number | (failureCount: number, error: TError) => boolean): 실패한 쿼리를 재시도하는 옵션
  • staleTime(number | 'static' | ((query: Query) => number | 'static')): 데이터가 fresh 상태로 유지되는 시간
  • gcTime(number | Infinity): 사용되지 않는 데이터의 보관 기간.

나머지 옵션들은 여기를 들어가보자..

useMutation

useMutation Hook으로 수행되는 Mutation 요청은 POST, PUT, DELETE와 같이 서버에 Side Effect를 발생시켜 서버의 상태를 변경시킬 때 사용한다.

const { mutate, isPending, isError, isSuccess } = useMutation({
    // data -> API 성공 응답데이터
    mutationFn: postLike,
    onSuccess: (data) => {
      queryClient.invalidateQueries({
        queryKey: [QUERY_KEY.lps, data.data.lpId],
        exact: true,
      });
    },
  });

useMutate의 흐름
mutate({ lpId: Number(lpid) }) 실행 -> postLike 성공 -> onSuccess 실행 -> queryKey: [QUERY_KEY.lps, data.data.lpId] 해당 queryKey에 등록된 queryFn 함수를 통해 서버로 데이터를 재요청 -> Tanstack Query가 자동으로 Re-fetch

useMutation의 주요 옵션들

  • mutationFn: Mutation 요청을 수행하기 위한 Promise를 Return 하는 함수
  • onSuccess: mutate가 성공했을 때 실행되는 함수
  • onError: mutate가 실패했을 때 실행되는 함수
  • onSettled: API 요청이 끝난 후(성공하든 실패하든 실행)
  • onMutate: mutate가 시작되기 전에 실행되는 함수 -> 낙관적 업데이트

이번에도 mutate, isPending, isError, isSuccess를 구조 분해 할당으로 손쉽게 사용할 수 있다.

이번에도 더 많은 옵션들은 여기

마무리

솔직히 useState 있고, useEffect 있는데 굳이 귀찮게 익숙한거 버리고 써야하나? 라는 생각이 있었는데 정리해보니 처음이라 어렵지 익숙해지면 정말 이것만큼 간편한게 없다고 생각이 든다..

단순히 내가 간편해서 좋은 라이브러리가 아니라, 캐싱을 효율적으로 관리해주기도 하고, 코드가 짧아지고 기능이 단순해진 덕에 유지보수에도 좋다고 한다. 다들 써본적이 없다면 이번 기회에 한번 같이 알아보는 건 어떨까..

https://tanstack.com/

https://junhee1203.tistory.com/22

https://velog.io/@kimhyo_0218/React-Query-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%BF%BC%EB%A6%AC-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-useQuery

https://tech.kakaopay.com/post/react-query-1/

profile
Hello World

3개의 댓글

comment-user-thumbnail
2025년 11월 18일

요즘 코드를 작성하면서 useState를 너무 많이 사용해서 고민이었는데 조만간 꼭 사용해봐야겠어요..!!!

답글 달기
comment-user-thumbnail
2025년 11월 24일

useState로 귀찮게 관리할 필요없이 useQuery로 편하게 상태관리하는 방법도 있군요
효율적인 라이브러리를 잘 사용하는 것이 여러면에서 중요하다는 것을 느꼈어요 굿굿..!

답글 달기
comment-user-thumbnail
2025년 11월 25일

아직도 useEffect와 useState에서 벗어나지 못하는 감자도 useQuery를 감히 도전해보아도 될까요 .. 다음에 꼭 사용해볼 기회가 있었으면 좋겠어요

답글 달기