리액트 라우터 프레임워크 데이터 패칭

김현준·2026년 4월 16일

리액트 이모저모

목록 보기
30/31

리액트 라우터 v7 + TanStack Query 조합에서
외부 API 데이터를 가져오는 구조는 “라우팅 + 쿼리 훅 분리”가 핵심이다


✅ 1. 기본 구조

src/
 ├── api/
 │    └── fetchPosts.ts
 ├── hooks/
 │    └── usePosts.ts
 ├── pages/
 │    └── PostsPage.tsx
 ├── router.tsx
 └── main.tsx

✅ 2. API 함수 (fetch layer)

👉 여기서 외부 API 호출만 담당

// api/fetchPosts.ts
export async function fetchPosts() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts");

  if (!res.ok) {
    throw new Error("데이터 불러오기 실패");
  }

  return res.json();
}

✅ 3. TanStack Query 훅

👉 React 컴포넌트는 이 훅만 사용하게 만든다

// hooks/usePosts.ts
import { useQuery } from "@tanstack/react-query";
import { fetchPosts } from "../api/fetchPosts";

export function usePosts() {
  return useQuery({
    queryKey: ["posts"],
    queryFn: fetchPosts,
  });
}

✅ 4. 페이지 컴포넌트

// pages/PostsPage.tsx
import { usePosts } from "../hooks/usePosts";

export default function PostsPage() {
  const { data, isLoading, isError } = usePosts();

  if (isLoading) return <div>로딩중...</div>;
  if (isError) return <div>에러 발생</div>;

  return (
    <div>
      <h1>게시글 리스트</h1>
      <ul>
        {data.map((post: any) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

✅ 5. React Router v7 설정

// router.tsx
import { createBrowserRouter } from "react-router";
import PostsPage from "./pages/PostsPage";

export const router = createBrowserRouter([
  {
    path: "/",
    element: <PostsPage />,
  },
]);

✅ 6. QueryClient + Router 연결

// main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider } from "react-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { router } from "./router";

const queryClient = new QueryClient();

ReactDOM.createRoot(document.getElementById("root")!).render(
  <QueryClientProvider client={queryClient}>
    <RouterProvider router={router} />
  </QueryClientProvider>
);

🎯 결과 UI

게시글 리스트
- 제목1
- 제목2
- 제목3
...

💡 핵심 포인트 (중요)

1. 역할 분리

  • fetch 함수 → API 통신만
  • useQuery → 캐싱 + 상태관리
  • 컴포넌트 → UI

2. React Router는 “페이지 이동만”

👉 데이터는 TanStack Query가 담당


3. 실무 확장 패턴

너 지금 하는 구조 기준으로는 이렇게 확장한다:

queryKey: ["posts", { page, keyword }]

👉 검색, 페이지네이션까지 바로 확장 가능


🔥 한 단계 위 (실무에서 많이 쓰는 패턴)

👉 라우터 + 프리패칭 같이 쓰기

// router.tsx
import { queryClient } from "./queryClient";
import { fetchPosts } from "./api/fetchPosts";

export const router = createBrowserRouter([
  {
    path: "/",
    loader: () =>
      queryClient.ensureQueryData({
        queryKey: ["posts"],
        queryFn: fetchPosts,
      }),
    element: <PostsPage />,
  },
]);

👉 페이지 들어가기 전에 데이터 미리 가져옴 (UX 좋아짐)


정리

  • React Router v7 → 라우팅 담당
  • TanStack Query → 서버 데이터 관리
  • 둘은 완전히 분리해서 쓰는 게 정석
profile
기록하자

0개의 댓글