한번쯤 들어본 FE 기술

비동기 데이터 처리(React Query)

프론트루나 2025. 3. 12. 07:54
반응형

React Query를 사용하여 API 호출과 비동기 데이터를 관리했음.

서버 상태 관리를 위한 라이브러리로, 데이터 페칭, 캐싱, 동기화, 업데이트 등을 쉽게 처리할 수 있게 해준다.

API 호출을 후 데이터 캐싱, 자동 리페칭, 로딩/에러 상태 관리 등을 자동으로 해준다.

useState, useEffect 없이도 데이터 가져오기 가능

핵심 기능

  1. 데이터 캐싱
  2. queryKey를 기준으로 데이터를 자동 캐싱하여 불필요한 API 호출 방지. 새로고침 해도 데이터를 유지할 수 있음
  3. 자동 리패칭(데이터 동기화)staleTime, refreshInterval 옵션을 사용하여 주기적으로 API 호출 가능
  4. 백그라운드에서 데이터를 자동 업데이트,
  5. 데이터 갱신(mutations)
  6. useMutation을 사용하면 POST, PUT, DELETE 같은 요청도 쉽게 처리 가능

🎯 React Query를 언제 써야 할까?

서버 데이터를 자주 가져와야 할 때

데이터 캐싱이 필요할 때

로딩 상태 & 에러 처리를 간단하게 하고 싶을 때

데이터가 변경될 때마다 새로고침 없이 자동 업데이트하고 싶을 때

query vs. mutation

  • query : 데이터를 가져오는 작업(GET 요청)
  • mutation : 데이터를 변경하는 작업(POST, PUT, DELETE 요청)

query status

const {
	data, // 쿼리 결과 데이터 
	isLoading, // 첫 로딩중인지 여부
	isError, // 오류 발생 여부
	error,  // 오류 객체
	isFetching, // 백그라운드에서 데이터를 가져오는 중인지 여부
	refetch // 수동으로 쿼리를 다시 실행하는 함수
} = useQuery({
	queryKey : ['todos'], // 캐싱 키 
	queryFn : () => axios.get("<https://api.example.com/data>").then((res) => res.data),
	})

react Query 기본설정

🚀 QueryClientProvider란?

react Query를 사용할 때, 전체 애플리케이션에서 React Query의 상태를 관리하는 역할

필요한 이유 (없으면 오류!)

  • QueryClientProvider가 없으면 React Query의 전역 상태를 관리할 수 없어서 오류
  • React Query는 내부적으로 데이터를 캐싱하고 상태를 관리하는 Query Client를 사용한다.
  • 이 Query Client를 앱 전체에서 공유하려면 QueryClientProvider로 감싸야 한다.
    • API 요청을 할 때, 데이터를 전역적으로 캐싱 & 관리
    • 자동으로 데이터 새로고침(탭 이동 시 최신 데이터 유지)
    • React Query 훅(useQuery, useMutation)을 사용하려면 필수..!
const queryClient = new QueryClient(); // QueryClient 인스턴스를 생성
<QueryClientProvider client={queryClient}> // 전역적으로 상태 관리 가능
</QueryClientProvider>

// queryClient 가 제공하는 주요 기능
const queryClient = new QueryClient({
	defaultOptions: {
		queries : {
			staleTime : 1000 * 60 * 5 // 5분 동안 캐싱 유지(5분동안 데이터 유지, 새로운 요청 방지)
		}
	}
})

🚀 정리

QueryClientProvider 역할

QueryClient React Query의 전역 상태 관리 객체
QueryClientProvider 전체 애플리케이션에서 QueryClient를 사용할 수 있도록 함
useQuery, useMutation API 요청을 간편하게 하고, 상태를 자동 관리

✔ QueryClientProvider를 사용해야 React Query 기능(useQuery, useMutation)을 정상적으로 사용할 수 있음

자동 캐싱, 리패칭, 최적화 기능 제공! 🚀

useQuery Hook

useQuery는 React Query에서 데이터를 가져오는 훅.

fetch, axios등을 직접 쓰지 않고도 자동으로 데이터 가져오기 + 캐싱 + 로딩/에러상태 관리

useQuery 주요 옵션

  • queryKey : 쿼리를 식별하는 고유 키
  • queryFn : 데이터를 가져오는 비동기 함수
  • staleTime : 데이터가 ‘fresh’하다고 간주되는 시간
  • retry : 실패 시 재시도 여부
  • refetchOnWindowFocus : 창으로 다시 돌아오면 자동으로 데이터 새로 고침 (boolean)
      refetchOnWindowFocus: false, // 윈도우 포커스 시 자동 리페치 비활성화
  • enabled : !!userID // userID가 있을 때만 실행
function Example() {
  // 1. useQuery 사용
  const { data, isLoading, error } = useQuery({
    queryKey: ["exampleData"], // 데이터 캐싱을 위한 키 queryKey : ["posts", 1] posts는 카테고리 이름, 1은 ID 값 // 동일한 쿼리 키가 있으면 자동으로 캐싱하여 중복 API 요청 방지 
    queryFn: () => axios.get("<https://jsonplaceholder.typicode.com/posts/1>").then((res) => res.data), // API를 호출하고 데이터를 반환하는 역할
  });

  // 2. 로딩 상태 처리
  if (isLoading) return

Loading...

;

  // 3. 에러 상태 처리
  if (error) return

Error occurred

;

  // 4. 성공 시 데이터 표시
  return
{data.title}
;
}

useMutation Hook

useMutation은 React Query에서 데이터를 변경(POST, PUT, DELETE 등)할 때 사용하는 훅이에요. 우리 챗토리 앱에서는 챗봇의 응답을 가져오고, 대화 내역을 저장하는데 사용했다.

 export const useChatQuery = () => {
  const addMessage = useChatStore((state: any) => state.addMessage);
  const setIsBotTyping = useChatStore((state: any) => state.setIsBotTyping);
  
  return useMutation({
    mutationFn: fetchChatbotResponse, // API 호출 함수
    onMutate: () => {
    // mutation 시작 전 실행
      setIsBotTyping(true); // 입력중 상태로 변경
    },
    // 성공시 실행
    onSuccess: (data) => {
      addMessage("assistant", data);
      setIsBotTyping(false);
    },
    // 실패시 실행
    onError: (error) => {
      console.error("챗봇 응답 실패:", error);
      setIsBotTyping(false);
    },
  });
};

// 사용
chatMutation.mutate([{role:"user", content: input}]];

useMutation 주요 옵션

  • mutationFn : 실행할 비동기 함수
  • onMutate: 뮤테이션 시작 전 실행할 함수
  • onSuccess : 성공 시 실행할 함수
  • onError : 실패 시 실행할 함수

🚀 useMutation vs useQuery

기능 useQuery useMutation

사용 목적 데이터를 가져올 때 (GET) 데이터를 변경할 때 (POST, PUT, DELETE)
자동 실행 여부 컴포넌트 마운트 시 자동 실행 mutate()를 호출해야 실행됨
캐싱 자동으로 데이터 캐싱 직접 invalidateQueries를 호출해야 갱신됨
로딩 상태 isLoading isPending
에러 상태 error error

🔄 useQuery와 함께 사용 (데이터 갱신)

데이터를 추가/수정/삭제한 후, 자동으로 화면을 갱신하고 싶다면?

👉 queryClient.invalidateQueries(["queryKey"])를 사용하면 돼요! 🚀

tsx
복사편집
import { useMutation, useQueryClient } from "@tanstack/react-query";
import axios from "axios";

function AddPost() {
  const queryClient = useQueryClient(); // ✅ QueryClient 가져오기

  const mutation = useMutation({
    mutationFn: (newPost) => axios.post("/api/posts", newPost),
    onSuccess: () => {
      queryClient.invalidateQueries(["posts"]); // ✅ posts 데이터를 새로고침
    },
  });

  return (
    <button onClick={() => mutation.mutate({ title: "새 게시글" })}>
      게시글 추가
    </button>
  );
}

✔ queryClient.invalidateQueries(["posts"])를 호출하면

✔ "posts" 데이터를 다시 불러와서 자동으로 최신 상태 유지! 🚀

반응형