React

React 19 Data Caching (map, React Query, swr)

arkhyeon 2025. 1. 13. 09:41
728x90
반응형

Map 객체를 활용한 데이터 캐싱

요청했던 URL과 데이터를 Map에 저장하므로 동일한 요청은 서버에 다시 호출하지 않고, 저장된 데이터를 반환합니다.

data.js

import { axios } from "./axios.js";

let cache = new Map();

export function fetchData(url) {
  if (!cache.has(url)) {
    cache.set(url, getData(url));
  }
  return cache.get(url);
}

async function getData(url) {
  if (url.startsWith("/search?q=")) {
    return await getSearchResults(url.slice("/search?q=".length));
  } else {
    throw Error("Not implemented");
  }
}
async function getSearchResults(query) {
  // Add a fake delay to make waiting noticeable.
  await new Promise((resolve) => {
    setTimeout(resolve, 500);
  });
  const a = await axios.get(`/departments/${query}`);

  return a.data.departments;
}
  • 캐시가 Map에 무한정 쌓이고 오래된 데이터가 계속 유지될 수 있습니다.
  • 현재 캐시는 해당 컴포넌트 내에서만 사용됩니다. 여러 컴포넌트에서 캐시를 유지하려면 context나 전역 상태 관리 라이브러리가 필요합니다.

React Query

복잡한 데이터 흐름과 상태 관리가 필요한 대규모 프로젝트 용이

import { useQuery } from '@tanstack/react-query';
import axios from 'axios';

const fetchDepartments = async (query) => {
  const response = await axios.get(`/departments/${query}`);
  return response.data.departments;
};

const DepartmentList = ({ query }) => {
  const { data, isLoading, error } = useQuery(
    ['departments', query],
    () => fetchDepartments(query),
    { staleTime: 300000 } // 캐시 데이터 유지 시간
  );

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading data</p>;

  return (
    <ul>
      {data.map((dept) => (
        <li key={dept.id}>{dept.name}</li>
      ))}
    </ul>
  );
};

export default DepartmentList;

SWR

소규모 프로젝트나 간단한 데이터 패칭만 필요한 경우 용이

import useSWR from 'swr';
import axios from 'axios';

const fetcher = (url) => axios.get(url).then((res) => res.data.departments);

const DepartmentList = ({ query }) => {
  const { data, error, isLoading } = useSWR(`/departments/${query}`, fetcher);

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading data</p>;

  return (
    <ul>
      {data.map((dept) => (
        <li key={dept.id}>{dept.name}</li>
      ))}
    </ul>
  );
};

export default DepartmentList;

 

여러가지 데이터 캐싱 방법이 있으니 용도에 맞춰 사용하시면 되겠습니다.

Layout

App.jsx

import { Suspense, useState} from "react";
import Department from "./Department.jsx";

function App() {
  const [id, setId] = useState(0);

  return (
    <div className="min-h-screen bg-gray-100 p-6">
      <input type="number" value={id} onChange={(e) => setId(Number(e.target.value))} />
      <Suspense fallback={<Loading />}>
        <div className="mb-6">
          <Department id={id} />
        </div>
      </Suspense>
    </div>
  );
}

export default App;

function Loading() {
  return <h2>🌀 Loading...</h2>;
}

Department.jsx

Department.jsx

//Department.jsx
import { use } from "react";
import { fetchData } from "./data.js";

function Department({ id }) {
  const department = use(fetchData(`/search?q=${id}`));

  if (id === 0) {
    return null;
  }

  return (
    <div>
      {department.map((dm) => (
        <div className="border border-gray-300 p-4 rounded-md" key={dm.departmentId} >
          <h2 className="text-xl font-bold mb-2">이름 : {dm.name}</h2>
          <p className="text-gray-600">ID: {dm.departmentId}</p>
          <p className="text-gray-600">설명: {dm.description}</p>
          <p className="text-gray-600">위치: {dm.location}</p>
        </div>
      ))}
    </div>
  );
}

export default Department;
728x90
반응형