[React] React Query (2)

조수현·2025년 9월 28일

서론

실제로 리액트쿼리를 적용해 데이터를 캐시하는 과정과
캐시 적용 전 후 차이를 봅시다

쿼리 적용 전

코드

import ProfileItem from "./ProfileItem";
import { User } from "../types/User";
import { useEffect, useState } from "react";
import { fetchUsers } from "../utils/users";

function Basic() {
  const [users, setUser] = useState<User[]>([]);
  const [isLoading, setIsLoading] = useState(true);

  const prepareUsers = async () => {
    const result = await fetchUsers();

    setUser(result);
    setIsLoading(false);
  };

  useEffect(() => {
    prepareUsers();
  }, []);

  const userMap = users.map((user, idx) => {
    return <ProfileItem key={idx} {...user} />;
  });

  return (
    <section className="w-80">
      <h2 className="text-2xl font-bold  justify-self-center">쿼리 사용 전</h2>
      <ul>{isLoading ? <span>Loading...</span> : userMap}</ul>
    </section>
  );
}

export default Basic;

쿼리 적용 후

코드

import { useQuery } from "@tanstack/react-query";
import ProfileItem from "./ProfileItem";
import { fetchUsers } from "../utils/users";

function Query() {
  const {
    isLoading,
    data: users,
  } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers,
  });


  const userMap = (users ?? []).map((user, idx) => {
    return <ProfileItem key={idx} {...user} />;
  });

  return (
    <section className="w-80">
      <h2 className="text-2xl font-bold  justify-self-center">쿼리 사용 후</h2>
      <ul>{isLoading ? <span>Loading...</span> : userMap}</ul>
    </section>
  );
}

export default Query;

쿼리 적용의 장점

확실히 또 이론 공부보다 직접 작성해 봐야한다고 느꼈다

  • data 하나만 사용했을 때도 코드가 단축되는 장점이 있음
  • 캐시 처리 로직까지 들어가면 더더욱 코드 단축이 됨
  • 사용자 경험을 위해 데이터 페칭 시 필수인 loading 처리 로직까지 편리하게 사용 가능

문제 상황

확실히 또 이론 공부보다 직접 작성해 봐야한다고 느꼈다222
지난 주에 올린 글로 리액트쿼리 사용 법을 다 알았다고 생각하고 오늘 글은 간단하겠지 했는데,,,,

  • 캐싱된 데이터를 불러오는 상황에서는 loading이 보이면 안 되는데 ,,, 보인다,,,
  • 내가 생각한 캐싱된 데이터를 불러오는 건 새로고침 시에도 이전 캐싱된 데이터를 유지하는 것인데 동작은 그렇질 못했다

  • 리액트 쿼리를 사용한 컴포넌트가 더 늦게 렌더링 된다
  • 이건 뭔가 순서의 영향이 있는 것 같아서 컴포넌트 순서를 바꿔봤다

문제 해결 1 - 컴포넌트 순서 변경

  • 컴포넌트 순서 변경을 했을 땐 jsx상 먼저 있는 컴포넌트가 먼저 렌더링 된다

  • 그것보다 순서를 변경하면서 발견한 점은
  • 컴포넌트 수정하고 저장할 때 보면 캐싱이 되고 있는 것으로 보인다

  • 아 설정 문제구나 싶었다

문제 해결 2 - react query 설정 변수

  • staleTime이 기본값 0이라고 지정하라는 글이 있어서 해 봤다
   const { isLoading, data: users } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers,
    staleTime: 1000 * 60 * 4 // 4분 동안 불러온 데이터 유지
  });
  • 여전히 안 됐음

문제 해결 3 - placeholderData

  • 나는 로딩이 보이고 싶지 않은 것
  • 사용자로 하여금 이전에 방문했던 페이지의 데이터가 로딩 없이 바로 보여 사용자 경험을 높이는 것이 목적이었다
  • 내가 생각한 리액트 쿼리의 캐싱 기능이 달랐기 때문에 다른 설정값을 사용하기로 했다
  const { isLoading, data: users } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers,
    staleTime: 1000 * 60 * 4,
    placeholderData: (prevData) => prevData,
  });

마무리

사실 원래 글에 덧붙이려고 하다가 리액트쿼리 캐시 적용이 내가 원하는 생각한대로 진행되지 않아 따로 빼봤다
별 거 아닐 수도 있는데 기록용으로 작성해 봤다

profile
프론트엔드 개발 블로그

0개의 댓글