Docs
Guide
Virtual File Routes

Virtual File Routes

Remix 팀이 가상 파일 라우트 개념을 개척 (opens in a new tab)한 것에 감사를 표합니다. 우리는 그들의 작업에서 영감을 받아 TanStack Router의 기존 파일 기반 라우트 트리 생성과 함께 작동하도록 조정했습니다.

가상 파일 라우트는 프로젝트 내 실제 파일을 참조하는 코드를 사용하여 라우트 트리를 프로그래밍 방식으로 구축할 수 있는 강력한 개념입니다. 이는 다음과 같은 경우에 유용할 수 있습니다:

  • 기존의 라우트 구성을 유지하고 싶은 경우.
  • 라우트 파일의 위치를 사용자 정의하고 싶은 경우.
  • TanStack Router의 파일 기반 라우트 생성을 완전히 무시하고 자신의 방식을 구축하고 싶은 경우.

다음은 프로젝트의 실제 파일 집합에 라우트 트리를 매핑하기 위해 가상 파일 라우트를 사용하는 간단한 예입니다:

import {
  rootRoute,
  route,
  index,
  layout,
  physical,
} from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [
  index("index.tsx"),
  layout("layout.tsx", [
    route("/dashboard", "app/dashboard.tsx", [
      index("app/dashboard-index.tsx"),
      route("/invoices", "app/dashboard-invoices.tsx", [
        index("app/invoices-index.tsx"),
        route("$id", "app/invoice-detail.tsx"),
      ]),
    ]),
    physical("/posts", "posts"),
  ]),
]);

Configuration

가상 파일 라우트는 다음 방법으로 구성할 수 있습니다:

  • Vite/Rspack/Webpack을 위한 TanStackRouter 플러그인
  • TanStack Router CLI의 tsr.config.json 파일

Configuration via the TanStackRouter Plugin

TanStackRouter 플러그인을 사용 중이라면, 플러그인에 virtualRoutesConfig 옵션을 전달하여 가상 파일 라우트를 구성할 수 있습니다:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
import { rootRoute } from "@tanstack/virtual-file-routes";
 
const routes = rootRoute("root.tsx", [
  // ... 나머지 가상 라우트 트리
]);
 
export default defineConfig({
  plugins: [TanStackRouterVite({ virtualRouteConfig: routes }), react()],
});

Creating Virtual File Routes

가상 파일 라우트를 생성하려면 @tanstack/virtual-file-routes 패키지를 가져와야 합니다. 이 패키지는 프로젝트 내 실제 파일을 참조하는 가상 라우트를 생성할 수 있는 함수를 제공합니다. 패키지에서 몇 가지 유틸리티 함수가 내보내집니다:

  • rootRoute - 가상 루트 라우트를 생성합니다.
  • route - 가상 라우트를 생성합니다.
  • index - 가상 인덱스 라우트를 생성합니다.
  • layout - 가상 레이아웃 라우트를 생성합니다.
  • physical - 물리적 가상 라우트를 생성합니다 (자세한 내용은 이후 참고).

Virtual Root Route

rootRoute 함수는 가상 루트 라우트를 생성하는 데 사용됩니다. 파일 이름과 하위 라우트 배열을 매개변수로 받습니다. 다음은 가상 루트 라우트의 예입니다:

import { rootRoute } from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [
  // ... children routes
]);

Virtual Route

route 함수는 가상 라우트를 생성하는 데 사용됩니다. 경로, 파일 이름, 하위 라우트 배열을 매개변수로 받습니다. 다음은 가상 라우트의 예입니다:

import { route } from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [
  route("/about", "about.tsx", [
    // ... children routes
  ]),
]);

파일 이름 없이 가상 라우트를 정의할 수도 있습니다. 이를 통해 자식 라우트에 공통 경로 접두사를 설정할 수 있습니다:

import { route } from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [
  route("/hello", [
    route("/world", "world.tsx"), // 전체 경로는 "/hello/world"가 됩니다.
    route("/universe", "universe.tsx"), // 전체 경로는 "/hello/universe"가 됩니다.
  ]),
]);

Virtual Index Route

index 함수는 가상 인덱스 라우트를 생성하는 데 사용됩니다. 파일 이름을 매개변수로 받습니다. 다음은 가상 인덱스 라우트의 예입니다:

import { index } from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [index("index.tsx")]);

Virtual Layout Route

layout 함수는 가상 레이아웃 라우트를 생성하는 데 사용됩니다. 파일 이름, 하위 라우트 배열, 선택적으로 레이아웃 ID를 매개변수로 받습니다. 다음은 가상 레이아웃 라우트의 예입니다:

import { layout } from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [
  layout("layout.tsx", [
    // ... children routes
  ]),
]);

레이아웃 ID를 지정하여 파일 이름과 다른 고유 식별자를 레이아웃에 부여할 수도 있습니다:

import { layout } from "@tanstack/virtual-file-routes";
 
const virtualRouteConfig = rootRoute("root.tsx", [
  layout("my-layout-id", "layout.tsx", [
    // ... children routes
  ]),
]);

Physical Virtual Routes

물리적 가상 라우트는 특정 URL 경로 아래에 기존 TanStack Router 파일 기반 라우팅 규칙의 디렉토리를 "마운트"하는 방법입니다. 이는 계층 구조의 상위에서 라우트 트리의 일부를 가상 라우트로 사용자 정의하려는 경우 유용하며, 하위 라우트 및 디렉토리에는 표준 파일 기반 라우팅 규칙을 계속 사용할 수 있습니다.

다음 파일 구조를 예로 들어보겠습니다:

/routes
├── root.tsx
├── index.tsx
├── layout.tsx
├── app
│   ├── dashboard.tsx
│   ├── dashboard-index.tsx
│   ├── dashboard-invoices.tsx
│   ├── invoices-index.tsx
│   ├── invoice-detail.tsx
└── posts
    ├── index.tsx
    ├── $postId.tsx
    ├── $postId.edit.tsx
    ├── comments/
    │   ├── index.tsx
    │   ├── $commentId.tsx
    └── likes/
        ├── index.tsx
        ├── $likeId.tsx

posts를 제외한 모든 것을 사용자 정의한 라우트 트리로 설정한 다음, /posts 경로 아래에 posts 디렉토리를 마운트하기 위해 물리적 가상 라우트를 사용해 보겠습니다:

const virtualRouteConfig = rootRoute("root.tsx", [
  // 일반적인 가상 라우트를 설정
  index("index.tsx"),
  layout("layout.tsx", [
    route("/dashboard", "app/dashboard.tsx", [
      index("app/dashboard-index.tsx"),
      route("/invoices", "app/dashboard-invoices.tsx", [
        index("app/invoices-index.tsx"),
        route("$id", "app/invoice-detail.tsx"),
      ]),
    ]),
    // `/posts` 경로 아래에 `posts` 디렉토리 마운트
    physical("/posts", "posts"),
  ]),
]);

Virtual Routes inside of TanStack Router File Based routing

앞서 설명한 방법은 가상 라우트 설정 내에서 TanStack Router 파일 기반 라우팅 규칙을 사용하는 방법을 보여줍니다.
하지만 그 반대도 가능합니다.
앱의 주요 라우트 트리를 TanStack Router 파일 기반 라우팅 규칙을 사용하여 구성하고, 특정 하위 트리에 대해서는 가상 라우트 구성을 선택할 수 있습니다.

다음 파일 구조를 고려해보세요:

/routes
├── __root.tsx
├── foo
│   ├── bar
│   │   ├── __virtual.ts
│   │   ├── details.tsx
│   │   ├── home.tsx
│   │   └── route.ts
│   └── bar.tsx
└── index.tsx

__virtual.ts라는 특별한 파일을 포함하는 bar 디렉토리를 살펴보겠습니다. 이 파일은 생성기에게 이 디렉토리(및 하위 디렉토리)에 대해 가상 파일 라우트 구성을 사용하도록 지시합니다.

__virtual.ts는 해당 라우트 트리의 특정 하위 트리에 대한 가상 라우트를 구성합니다. 위에서 설명한 동일한 API를 사용하되, 이 하위 트리에 대해 rootRoute는 정의되지 않는다는 점만 다릅니다:

import {
  defineVirtualSubtreeConfig,
  index,
  route,
} from "@tanstack/virtual-file-routes";
 
export default defineVirtualSubtreeConfig([
  index("home.tsx"),
  route("$id", "details.tsx"),
]);

defineVirtualSubtreeConfig 헬퍼 함수는 Vite의 defineConfig와 유사하게 설계되었으며 기본 내보내기를 통해 하위 트리 구성을 정의할 수 있습니다. 기본 내보내기는 다음 중 하나일 수 있습니다:

  • 하위 트리 구성 객체
  • 하위 트리 구성 객체를 반환하는 함수
  • 하위 트리 구성 객체를 반환하는 비동기 함수

Inception

TanStack Router의 파일 기반 라우팅 규칙과 가상 라우트 구성을 자유롭게 혼합하여 사용할 수 있습니다.
더 깊이 탐구해 봅시다!
다음 예는 파일 기반 라우팅 규칙으로 시작하여 /posts에서 가상 라우트 구성을 사용하고, /posts/lets-go에서 파일 기반 라우팅 규칙으로 다시 전환하며, 마지막으로 /posts/lets-go/deeper에서 다시 가상 라우트 구성을 사용하는 사례를 보여줍니다.

├── __root.tsx
├── index.tsx
├── posts
│   ├── __virtual.ts
│   ├── details.tsx
│   ├── home.tsx
│   └── lets-go
│       ├── deeper
│       │   ├── __virtual.ts
│       │   └── home.tsx
│       └── index.tsx
└── posts.tsx

Configuration via the TanStack Router CLI

비교적 덜 일반적이지만, TanStack Router CLI를 통해 가상 파일 라우트를 구성할 수도 있습니다. tsr.config.json 파일에 virtualRouteConfig 객체를 추가하고, @tanstack/virtual-file-routes 패키지의 실제 rootRoute/route/index 등 함수를 호출하여 생성된 JSON을 정의합니다:

// tsr.config.json
{
  "virtualRouteConfig": {
    "type": "root",
    "file": "root.tsx",
    "children": [
      {
        "type": "index",
        "file": "home.tsx"
      },
      {
        "type": "route",
        "file": "posts/posts.tsx",
        "path": "/posts",
        "children": [
          {
            "type": "index",
            "file": "posts/posts-home.tsx"
          },
          {
            "type": "route",
            "file": "posts/posts-detail.tsx",
            "path": "$postId"
          }
        ]
      },
      {
        "type": "layout",
        "id": "first",
        "file": "layout/first-layout.tsx",
        "children": [
          {
            "type": "layout",
            "id": "second",
            "file": "layout/second-layout.tsx",
            "children": [
              {
                "type": "route",
                "file": "a.tsx",
                "path": "/layout-a"
              },
              {
                "type": "route",
                "file": "b.tsx",
                "path": "/layout-b"
              }
            ]
          }
        ]
      }
    ]
  }
}