Tanstack Router 기본 사용법 및 가이드 (File-based Routing)
React Router를 대체할 수 있는 File-based Routing 방식인 Tanstack Router의 기본 사용법과 가이드를 알아봅니다.
소개
Tanstack Router는 React Router를 대체할 수 있는 라이브러리입니다.
React Router도 많은 사람들이 사용하고 있지만, Tanstack Router는 React Router보다 더 간편하고 빠르게 사용할 수 있습니다.
우선 Tanstack Router는 File-based Routing
을 지원합니다.
File-based Routing이 아니라도 사용할 수 있습니다.
tanstack router
의 가장 큰 장점으로는 자동 라우팅 코드 생성과, 강력한 타입 안전성을 들 수 있습니다.
잘못된 경로와 오타로 인한 라우팅 오류를 런타임 및 컴파일 시점에 잡아낼 수 있습니다.
그리고
Link
컴포넌트에서to
속성을 통한 경로 자동 완성(Intellisense) 기능을 제공합니다.
요즘 핫한 React Framework인 Next.js에서도 기본적으로 File-based Routing을 사용합니다.
저도 주로 Next.js를 사용하고 있고, Code Based Routing을 사용하는 기존 React Router 방식보다, File-based Routing을 사용하는 Tanstack
Route 방식이 더 편하고, Next.js와 비슷한 방식은 File-based Routing
이기 때문에 더 편리하다고 느껴졌습니다.
이 글에서는 Tanstack Router의 사용법과 가이드를 알아보겠습니다.
목차
- Tanstack Router 설치
- 프로젝트 설정
- 프로젝트 파일 구성
- __root 파일 설정
- main 파일 설정
- 서브페이지 라우트 생성
- 추가 라우트 생성
- Header 컴포넌트 추가
- 서브페이지의 하위 라우트 생성
- 개별 Layout 설정
Tanstack Router 설치
설치
npm install @tanstack/react-router
# or
pnpm add @tanstack/react-router
# or
yarn add @tanstack/react-router
# or
bun add @tanstack/react-router
vite 프로젝트에서는 다음과 같이 두가지 패키지를 설치해야 합니다.
npm install -D @tanstack/router-plugin @tanstack/router-devtools
# or
pnpm add -D @tanstack/router-plugin @tanstack/router-devtools
# or
yarn add -D @tanstack/router-plugin @tanstack/router-devtools
# or
bun add -D @tanstack/router-plugin @tanstack/router-devtools
@tanstack/router-plugin
은vite
빌드 시 플러그인으로 사용되고,@tanstack/router-devtools
는 개발 모드에서 개발자 도구로 사용됩니다.
위 설치 방법 외에 tanstack router에서는 간단하게 통합 패키지 설치를 지원합니다.
npm create @tanstack/router@latest
# or
pnpm create @tanstack/router
# or
yarn create @tanstack/router
# or
bun create @tanstack/router
위 명령어를 실행하고 메세지에 따라 설치를 진행하면 됩니다.
프로젝트 설정
필요한 tanstack router 패키지를 설치하고 나면 프로젝트 설정을 진행해야 합니다.
우선 vite 플러그인을 구성합니다. 해당 파일은 vite.config.ts
파일입니다.
// vite.config.ts
import { defineConfig } from "vite";
import viteReact from "@vitejs/plugin-react"; // 또는 import viteReact from '@vitejs/plugin-react-swc'
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
TanStackRouterVite(),
viteReact(), // import 이름은 어느것을 사용해도 상관없습니다. (viteReact, react)
// ...,
],
});
Import 이름은 Default Export라서 경로만 일치한다면 이름을 어느것을 사용해도 상관없습니다. (viteReact, react)
초기 vite 설치시 swc를 사용하고 있다면
import react from '@vitejs/plugin-react-swc'
경로를 사용해 주세요.
기본 설정은 간단하게 위와 같이 설정해 주면 됩니다.
이제 프로젝트에서 사용할 파일을 생성해 주어야 합니다.
프로젝트 파일 구성
프로젝트 파일 구성은 다음과 같습니다.
src
├── routes
│ ├── __root.tsx // 최상위 루트 파일
│ ├── about.tsx
│ ├── posts/
│ │ ├── index.tsx
│ │ └── $postId.tsx
│ │ └── ...
│ └── ... // 추가 라우팅 파일
├── main.tsx // 진입점 파일
├── routeTree.gen.ts // 자동 생성 파일
└── ...
프로젝트 파일 구성은 routes 폴더에 라우팅 파일을 생성하고, 최상위 루트 파일은 __root.tsx
파일을 생성해 주면 됩니다.
File-based Routing
방식을 사용하기 때문에 라우팅 파일을 생성하면 자동으로 경로 트리가 생성됩니다.
웹사이트의 페이지가 필요하다면 반드시 routes 폴더에 라우팅 파일을 생성해 주어야 합니다.
__root 파일 설정
이제 우선 가장 기본이되는 파일인 routes 폴더에 __root.tsx
파일을 생성해 주어야 합니다.
__root.tsx
파일은 프로젝트의 최상위 루트 파일입니다.
__root.tsx
파일을 생성하면 __root.tsx
파일에 별도의 코드를 작성하지 않아도 자동으로 라우팅 코드가 생성됩니다.
import * as React from "react";
import { Outlet, createRootRoute } from "@tanstack/react-router";
export const Route = createRootRoute({
component: RootComponent,
});
function RootComponent() {
return (
<React.Fragment>
<div>Hello "__root"!</div>
<Outlet />
</React.Fragment>
);
}
tanstack router
의 장점중 하나는 라우팅 파일에 별도의 코드를 작성하지 않아도 생성한 파일의 이름을 기준으로 자동으로 라우팅 코드가 생성됩니다.
그리고 __root.tsx
파일 코드 생성과 함께 routeTree.gen.ts
파일이 자동으로 생성됩니다.
생성된 코드를 살펴봅시다.
createRootRoute
메서드는 라우팅 트리의 최상위 루트 라우트를 생성합니다.
인자로는 라우트 컴포넌트와 라우트 옵션을 받습니다.
src
├── routes
│ ├── __root.tsx
│ └── ...
├── routeTree.gen.ts // 자동 생성 파일
└── ...
routeTree.gen.ts
파일은 생성된 경로 트리를 가져와서 자동으로 새 라우터 인스턴스를 만듭니다.
고로 routeTree.gen.ts
파일은 별도의 코드를 작성 및 수정하지 않습니다.
이제 main.tsx
파일을 설정해 주어야 합니다.
main 파일 설정
main.tsx
파일은 프로젝트의 진입점 파일입니다.
import ReactDOM from "react-dom/client";
import { createRouter, RouterProvider } from "@tanstack/react-router";
// 생성된 경로 트리 가져오기
import { routeTree } from "./routeTree.gen";
import { StrictMode } from "react";
// 새 라우터 인스턴스 만들기
const router = createRouter({ routeTree });
// 유형 안전성을 위해 라우터 인스턴스 등록
declare module "@tanstack/react-router" {
interface Register {
router: typeof router;
}
}
// Render the app
const rootElement = document.getElementById("root")!;
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement);
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>
);
}
위와 같이 main.tsx
파일을 설정해 주면 됩니다.

최상위 루트 파일
Hello "__root"!
문구가 표시된 것을 확인할 수 있습니다.
앗! 그런데 Not Found
문구가 표시되는 것을 확인할 수 있습니다.
이것은 하위 라우트가 없기 때문에 발생하는 것입니다.
__root.tsx
파일은 최상위 루트 파일입니다. 자동으로 생성된 __root.tsx
파일을 자세히 보면 <Outlet />
컴포넌트가 있습니다.
<Outlet />
컴포넌트는 하위 라우트를 표시하는 컴포넌트입니다.
그러니 하위 라우트를 생성해 주어야 합니다.
서브페이지 라우트 생성
__root.tsx
파일에 하위 라우트를 생성해 주어야 합니다.
index.tsx
파일을 생성합니다. index.tsx
파일은 웹사이트의 메인 페이지를 의미합니다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx
│ └── ...
└── ...
index.tsx
파일을 생성하면 자동으로 라우팅 코드가 생성됩니다.
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({
component: RouteComponent,
});
function RouteComponent() {
return "Hello /!";
}
localhost:5173
주소로 접속하면 Hello /!
문구가 표시됩니다.
index.tsx
파일을 살펴 봅시다.
createFileRoute
메서드는 파일 기반 라우팅을 위한 라우트를 생성합니다. 인자로는 경로를 받습니다.
옵션으로는 라우트 컴포넌트를 받습니다.
__root.tsx
파일에Hello "__root"!
문자가 있다면 함께 나타날 것 입니다.
__root.tsx
파일의 div 엘리먼트를 삭제하고 <Outlet/>
컴포넌트만 남겨둡니다.
// ...
function RootComponent() {
return (
<React.Fragment>
<Outlet />
</React.Fragment>
);
}
기본적으로 메인 페이지까지 설정이 완료되었습니다.
이제 tanstack router
의 하위 컴포넌트 <Outlet/>
컴포넌트를 사용해 Header 컴포넌트를 추가하고 다른 페이지를 추가해 보겠습니다.
추가 라우트 생성
우선 추가 라우트를 생성하기 전에 라우트 트리를 살펴 봅시다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── about.tsx
│ └── ...
└── ...
about.tsx
파일을 생성하면 자동으로 라우팅 코드가 생성됩니다.
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/about")({
component: AboutPage,
});
// 함수 이름은 자유롭게 변경할 수 있습니다.
function AboutPage() {
return "Hello /about!";
}
AboutPage
함수 이름은 자유롭게 변경할 수 있습니다. 단, 라우트 컴포넌트 이름과 동일해야 합니다.
위에서 사용된 about
경로는 파일로 생성한 경로입니다.
파일 이름으로 생성한 라우트외에 폴더를 사용한 라우트도 있습니다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── about/
│ │ ├── index.tsx
│ │ └── ...
│ └── ...
└── ...
두가지 방법중 어느것을 사용해도 무관하나, 저는 각 페이지별 라우트를 정리할 수 있는 폴더를 생성하는 방법을 선호합니다.
next.js
의 라우팅 패턴도 폴더를 사용하는 방법이기 때문에 되도록이면 맞추는것이 좋다고 생각합니다.
localhost:5173
주소로 접속하면 about 페이지가 표시됩니다.
이제 메인 페이지와 about 페이지가 완성되었습니다.
이제 Header 컴포넌트를 추가하고 Link 컴포넌트를 사용해 메인 페이지와 about 페이지를 이동해 보겠습니다.
Header 컴포넌트 추가
/components
폴더에 Header.tsx
파일을 생성합니다.
import { Link } from "@tanstack/react-router";
const Header = () => {
return (
<header className="header">
<h1>Tanstack Router</h1>
<nav className="navigation">
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
</header>
);
};
export default Header;
Link
컴포넌트는@tanstack/react-router
에서 제공하는 컴포넌트입니다.기존 react-router에서 사용하던
Link
컴포넌트와 동일한 기능을 제공합니다.Tanstack Router에서는 강력한 타입 안전성을 제공하기 때문에
Link
컴포넌트에서 잘못된 경로가 있으면 즉시 오류를 표시하고 해당 메세지에서 경로 제안도 해줍니다.

Header 컴포넌트
이제 메인 페이지와 about 페이지에 Header 컴포넌트를 추가해 보겠습니다.
메인 페이지와 about 페이지에 모두 한번에 Header 컴포넌트를 추가하기 위해 __root.tsx
파일을 이용합니다.
__root.tsx
파일은 앞서 말한바와 같이 최상위 루트 파일입니다.
따라서 메인 페이지와 about 페이지에 모두 한번에 Header 컴포넌트를 추가할 수 있습니다.
// ...
export const Route = createRootRoute({
component: RootComponent,
});
function RootComponent() {
return (
<React.Fragment>
<Header />
<Outlet /> {/* 하위 라우트를 표시하는 컴포넌트 */}
<Footer /> {/* footer는 예시 */}
</React.Fragment>
);
}
<Outlet />
컴포넌트는 하위 라우트를 표시하는 컴포넌트입니다.
<main>
엘리먼트 자식 요소로<Outlet />
컴포넌트를 추가할 수도 있습니다.
// ...
function RootComponent() {
return (
<Header />
<main>
<Outlet />
</main>
<Footer />
);
}
이제 메인 페이지와 about 페이지에 각각 Header 컴포넌트가 추가된 것을 확인할 수 있습니다.

메인 페이지에 추가된 Header 컴포넌트
tanstack router
에서는Link
컴포넌트에 기본적으로 해당 경로와 일치하는 경로에 대한active
클래스를 제공합니다.이를 이용하여 현재 페이지에 대한 스타일을 쉽게 적용할 수 있습니다.
.active {
color: yellow;
}
css 파일에서 .active
클래스를 사용하여 스타일을 설정할 수 있지만 Link
컴포넌트의 activeProps
옵션을 사용하여 스타일을 설정할 수도 있습니다.
// ...
<Link
to="/"
activeProps={{
style: {
color: "red",
},
}}
>
Home
</Link>
서브페이지의 하위 라우트 생성
tanstack-route
에서 서브페이지의 하위 라우트를 생성해 보겠습니다.
about/
폴더에 news.tsx
파일을 생성합니다.
폴더 구조는 다음과 같습니다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── about/
│ │ ├── index.tsx
│ │ └── news.tsx
│ └── ...
└── ...
news.tsx
파일을 생성하면 이전과 같이 자동으로 라우팅 코드가 생성됩니다.
about/index.tsx
파일에서 Link
컴포넌트를 사용하여 news
페이지로 이동할 수 있습니다.
// ...
<div>
<h1>About</h1>
<Link to="/about/news">News</Link>
</div>
Link
를 클릭하면 localhost:5173/about/news
주소로 이동합니다.
만약 폴더기반으로 라우팅을 사용한다면 about/
폴더에 news.tsx
파일을 생성해야 합니다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── about/
│ │ ├── index.tsx
│ │ └── news/
│ │ └── index.tsx
│ └── ...
└── ...
다른 서브페이지도 동일한 방법으로 생성할 수 있습니다.
개별 Layout 설정
tanstack router
에서는 개별 라우트에 대한 Layout을 설정할 수 있습니다.
여기서는 조금 복잡할 수 있습니다. 처음에는 이해하기 어려울 수 있습니다. 그러나 천천히 따라오면 이해할 수 있습니다.
개별 Layout
을 설정하기 위해서는 이전 폴더 구조를 변경해야합니다.
예시로 about 페이지와 contact 페이지를 추가하여 각 페이지에 대한 Layout
을 설정해 보겠습니다.
우선 _aboutLayout.tsx
파일을 생성합니다.
_aboutLayout.tsx
파일은 해당 route 폴더와 같은 위치에 생성해야 합니다.
그리고 기존 about
폴더를 _aboutLayout
폴더로 감싸야 합니다.
폴더 구조는 다음과 같습니다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx // 메인 페이지
│ ├── _aboutLayout/ // about 페이지의 Layout
│ │ ├── about/
│ │ │ └── index.tsx // about 페이지의 메인 페이지
│ │ │ └── news/
│ │ │ └── index.tsx // about 페이지의 news 페이지
│ ├── _aboutLayout.tsx
│ └── ...
└── ...
_aboutLayout/
폴더를 생성하고 about
폴더를 드래그하여 _aboutLayout
폴더로 이동합니다.
이제 _aboutLayout.tsx
파일을 설정합니다.
// ...
import { createFileRoute, Outlet } from "@tanstack/react-router";
export const Route = createFileRoute("/_aboutLayout")({
component: AboutLayout,
});
function AboutLayout() {
return (
<div>
<h1>About Layout</h1>
<Outlet />
{/* 하위 라우트를 표시하는 컴포넌트, 반드시 추가해야 합니다. */}
</div>
);
}
<Outlet />
컴포넌트는 반드시 추가해야 합니다. 그렇지 않으면 하위 라우트를 표시할 수 없습니다.
이제 네비게이션의 경로로 이동하면 About Layout
텍스트와 하위 라우트가 표시됩니다.

About Layout
다음은 contact
페이지를 추가하고 해당 페이지에 대한 Layout
을 설정해 보겠습니다.
방법은 about
페이지와 동일합니다.
_contactLayout.tsx
파일을 생성하고 contact
폴더를 _contactLayout
에 추가한 후 index.tsx 파일을 생성합니다.
폴더 구조는 다음과 같습니다.
src
├── routes
│ ├── __root.tsx
│ ├── index.tsx
│ ├── _aboutLayout/
│ │ ├── about/
│ │ │ └── index.tsx
│ │ └── news/
│ │ └── index.tsx
│ ├── _contactLayout/ // contact 페이지의 Layout
│ │ └── contact/
│ │ └── index.tsx
│ ├── _contactLayout.tsx
│ └── ...
└── ...
이제 _contactLayout.tsx
파일을 설정합니다.
import { createFileRoute, Outlet } from "@tanstack/react-router";
export const Route = createFileRoute("/_contactLayout")({
component: ContactLayout,
});
function ContactLayout() {
return (
<div>
<h1>Contact Layout</h1>
<Outlet />
</div>
);
}
나머지는 about
페이지와 동일하게 설정합니다.
이제 네비게이션의 경로로 이동하면 Contact Layout
텍스트와 하위 라우트가 표시됩니다.

Contact Layout
위 이미지를 보시는 바와같이 about
의 ABOUT LAYOUT
텍스트가 나타나지 않는것을 확인할 수있습니다.
이는 about
페이지에 대한 Layout
이 _aboutLayout.tsx
파일에 정의되어 있기 때문입니다.
또한 contact
페이지에 대한 Layout
이 _contactLayout.tsx
파일에 정의되어 있기 때문에 contact
페이지의 CONTACT LAYOUT
텍스트가 나타나는 것을 확인할 수 있습니다.
이를 이용해 각 페이지의 디자인 및 기능에 대해 개별적으로 적용 및 관리할 수 있습니다.
마치며
이제 기본적인 tanstack-route
의 각각의 경로 생성, 라우팅, Layout 설정 및 개별 Layout 설정 방법을 알아보았습니다.
내용이 길었습니다. 다음 포스팅에서는 tanstack-route
에서 제공하는 다이나믹 라우트 및 쿼리 기능에 대한 블로그를 작성해 보겠습니다.
GitHub 코드
다음 GitHub에서 코드를 확인할 수 있습니다.
`Tanstack Router Basic`