[React] 프로젝트에 TanStack Router 도입기

leem·2026년 3월 25일

tanstack router

개요

기존 React 프로젝트에서 라우팅은 React Router DOM을 기본적으로 사용했었지만, 이번 프로젝트에서부턴 TanStack Router를 도입하였다.

React Router와 TanStack Router

1) React Router DOM의 코드 라우팅 방식의 단점
React Router DOM은 라우트를 코드로 직접 선언하는 방식이다.

해당 방식에서 느낀 단점은 다음과 같다:

  • 페이지가 늘어날수록 선언부가 길어짐
  • 실제 파일이 어디에 있는지 별도로 추척이 필요
  • 라우트 설정과 컴포넌트 파일이 분리되어 있어 한 페이지를 추가할 때 두 곳을 동시에 수정해야 하는 번거로움

이 단점을 보완한 방식이 바로 TanStack Router이다.

TanStack Router?

TanStack Router는 파일 기반 라우팅을 지원한다.
파일을 만들면 라우트가 자동 등록되고, 파일 구조가 그대로 URL 구조가 된다.

⇒ 너무 편하다!

위와 같은 이유로, tanstack router를 실제 프로젝트에 도입하게 되었다.

해당 프로젝트는 react + vite + pnpm 을 기반으로 진행합니다.
차이점이 있을 경우 아래 내용과 다를 수 있으니 참고해주세요!

Tanstack Router 세팅하기

1. 패키지 설치

먼저, 다음의 내용을 터미널에 입력해 프로젝트 내에 tanstack-router 패키지를 설치한다.

pnpm add @tanstack/react-router
pnpm add -D @tanstack/router-plugin @tanstack/router-devtools

2. vite.config.ts 설정

설치를 마쳤다면, vite.config.ts 파일을 열어서 해당 라이브러리를 import 한 후, plugins에 추가해주자.

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    TanStackRouterVite(), // 반드시 react()보다 앞에 위치
    react(),
    tailwindcss(),
  ],
})

3. 라우트 파일 생성

src/ 폴더 내부에 routes 폴더를 만든 뒤 __root.tsx 를 생성한다.

import { createRootRoute, Outlet } from '@tanstack/react-router'

export const Route = createRootRoute({
  component: () => <Outlet />,
})

생성을 마쳤다면, pnpm dev으로 개발 서버를 실행해주자.
tanstack이 src/routeTree.gen.ts파일을 자동으로 생성해준다!

__root.tsx 파일 없이 실행할 경우 tanstack이 인식하지 못해 생성해주지 않는다 꼭 전부 설정한 후 진행하자.

4. router.ts 생성

routeTree.gen.ts 파일이 제대로 생성되었다면,
라우터 설정을 위한 router.ts 파일을 생성한다.

import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export const router = createRouter({ routeTree })

declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}

프로젝트 규모가 작은 경우 main.tsx 파일 내부에 설정해도 괜찮다!

5. main.tsx 설정

마지막으로 main.tsx 파일을 설정해주면 초기 세팅은 마무리된다.

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from '@tanstack/react-router'
import { router } from './router'
import './index.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>,
)

주의사항

  • App.tsx 는 TanStack Router 사용 시 불필요하니 삭제해주자.
  • routeTree.gen.ts 는 자동 생성되는 파일이므로, 직접 수정하면 오류가 날 수 있다!

TanStack Router 라우트 구조 패턴

tanstack router는 파일 기반 라우팅이다.
파일/폴더 구조가 그대로 URL 구조가 되는 방식이다.

  • Next.js 구조와 유사하다고 생각하면 된다.

1. 단일 페이지

페이지 하나만 있을 땐, 원하는 URL 이름으로 파일 명을 생성해주면 된다.

src/routes/
├── experience.tsx    # /experience
└── contact.tsx       # /contact
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/experience')({
  component: () => <div>경력 페이지</div>,
})

2. 폴더 구조 (Next.js 스타일)

이 방식은 중첩 라우트가 필요하지만, 공통 레이아웃이 없을 때 사용한다

src/routes/
└── projects/
    ├── index.tsx     # /projects
    └── $id.tsx       # /projects/:id
// src/routes/projects/$id.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/projects/$id')({
  component: () => <div>프로젝트 상세</div>,
})

3. route.tsx 패턴

하위 페이지들이 공통 레이아웃을 공유할 때 사용한다.
route.tsx가 레이아웃을 담당하고 <Outlet />으로 하위 페이지를 렌더링한다.

  • React Router v6의 Data Router 방식과 유사하다
src/routes/
└── projects/
    ├── route.tsx     # /projects 레이아웃 (헤더, 컨테이너 등 공통 UI)
    ├── index.tsx     # /projects
    └── $id.tsx       # /projects/:id
// src/routes/projects/route.tsx
import { createFileRoute, Outlet } from '@tanstack/react-router'

export const Route = createFileRoute('/projects')({
  component: () => (
    <div>
      {/* 공통 레이아웃 */}
      <Outlet />
    </div>
  ),
})

언제 뭘 쓸까?

상황패턴
페이지 하나, 중첩 없음단일 파일
중첩 라우트, 공통 레이아웃 없음폴더 구조
중첩 라우트 + 공통 레이아웃 필요route.tsx 패턴

주의사항

  • pnpm dev 실행 중이면 파일 저장 즉시 routeTree.gen.ts 자동 업데이트
  • $ 접두사는 동적 파라미터 — $id.tsx → URL에서 :id에 해당
  • route.tsx는 반드시 <Outlet />을 포함해야 하위 페이지가 렌더링됨
profile
한 줄의 코드로 세상을 변화 시키고 싶은 개발자 이서림 입니다.

0개의 댓글