Tanstack Router
는 Typescript의 타입 시스템을 활용하여 라우팅을 관리하며 타입 안전성을 보장하는 것을 목표로 설계되었다. 즉, 개발자가 런타임 오류를 사전에 방지하고 코드를 더욱 안정적으로 유지할 수 있게 한다.
Tanstack Router는
Code Splitting
을 통해 애플리케이션 성능 최적화를 위한 강력한 기능을 제공한다. Tanstack Router
에서는 크게 두 가지로 경로 설정을 구분하다.
Critical Route Configuration : 현재 경로를 렌더링 및 초기 페이지 로드 시 필요한 코드를 포함한다. (스크립트, 스타일, 로더 등)
Non-Critical/Lazy Route Configuration : 필요할 때 로드할 수 있는 코드를 포함한다. (라우트 컴포넌트, 에러 컴포넌트 등)
위와 같이 두 가지 경로 설정을 구분하여 동작함으로써 초기 로딩 시 필요한 리소스만 먼저 로드하여 페이지 성능을 개선하고, 나머지는 필요할 때 동적으로 로드하여 사용자 경험을 최적화할 수 있다.
또한, Tanstack Router
는 파일 기반의 라우팅 시스템을 지원하여 코드를 간편하게 분리할 수 있다. .lazy.tsx
를 통해 지연 로드 컴포넌트를 쉽게 정의하고 디렉터리로 경로 파일을 캡슐화하여 관리할 수 있다.
추가적으로 로더는 필요에 따라 비동기적으로 로드되고 실행될 수 있기 때문에 로더를 가져오고 실행하는 과정까지 기다려야하는 추가적인 비용이 발생한다. 이로 인해 로더 또한, Critical Route Configuration로 분류된다.
#How does TanStack Router split code?
Non-Critical/Lazy Route Configuration로 분류되는 코드 파일은 filename.lazy.tsx
과 같이 생성한다. createLazyFileRoute
를 사용하여 간단하게 구현할 수 있다. (__root.tsx
라우트 파일은 현재 경로와 관계없이 항상 렌더링 되기 때문에 코드 분할을 지원하지 않는다.)
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/')({
component: () => <div>Hello!</div>
})
// 아래 코드는 Code-Based Splitting를 사용하는 방법이다.
const postsRoute = createRoute({
getParent: () => rootRoute,
path: '/posts',
}).lazy(() => import('./posts.lazy').then((d) => d.Route))
createLazyFileRoute
에서 지원하는 옵션은 아래와 같다.
구분 | 내용 |
---|---|
component | - 렌더링시 사용되는 컴포넌트를 정의한다. |
errorComponent | - 라우트 로딩 중 오류가 발생했을 때 렌더링할 컴포넌트를 정의한다. |
pendingComponent | - 라우트가 로딩 중일 때 렌더링할 컴포넌트를 정의한다. |
notFoundComponent | - 404 / 잘못된 경로를 탐색할 때 렌더링할 컴포넌트를 정의한다. |
Tanstack Router
는 Route Tree
를 생성할 때, 아래 두 가지 방식을 지원한다.
(Tanstack Router
는 파일 기반 라우팅을 권장한다. 파일 기반 라우팅은 더 적은 코드로 동일하거나 더 나은 결과를 얻을 수 있다. 또한, 대부분의 공식 문서가 파일 기반 라우팅을 기준으로 작성되었다.)
Tanstack Router
는 중첩 라우팅을 설정하기 위해 라우팅 계층구조라 불리는 Route Tree
를 사용한다. (이를 통해 매칭되는 라우터 조직화 및 컴포넌트 트리로 구성한다.) Route Tree
는 여러 다양한 방법으로 정의하여 사용할 수 있다.
Flat Routes | - 동일 수준의 중첩을 사용한다. - 구조가 단순하고 이해하기 쉽다.(소규모 애플리케이션에 적합) |
---|---|
Directory Routes | - 계층적으로 중첩된 라우트를 나타내는 방식이다. - 관련있는 라우터를 조직화(묶음)하거나 깊게 중첩된 라우트 파일 이름 길이를 단순화시킬 수 있다. |
Mixed Flat and Directory Routes | - 중첩된 라우트를 표현하면서 단일 배열의 단순성을 유지할 수 있다. |
Code-Based Routes | - 코드 내에서 동적으로 라우트를 정의하는 방식이다. |
Case-Sensitivity | - 경로의 대소문자 구분을 설정할 수 있는 기능이다. |
Tanstack Router
는 Route Tree
를 생성할 때, 아래 두 가지 방식을 지원한다.
(Tanstack Router
는 파일 기반 라우팅을 권장한다. 파일 기반 라우팅은 더 적은 코드로 동일하거나 더 나은 결과를 얻을 수 있다. 또한, 대부분의 공식 문서가 파일 기반 라우팅을 기준으로 작성되었다.)
Tanstack Router
는 중첩 라우팅을 설정하기 위해 라우팅 계층구조라 불리는 Route Tree
를 사용한다. (이를 통해 매칭되는 라우터 조직화 및 컴포넌트 트리로 구성한다.) Route Tree
는 여러 다양한 방법으로 정의하여 사용할 수 있다.
종류 | 내용 |
---|---|
Flat Routes | - 동일 수준의 중첩을 사용한다. - 구조가 단순하고 이해하기 쉽다.(소규모 애플리케이션에 적합) |
Directory Routes | - 계층적으로 중첩된 라우트를 나타내는 방식이다. - 관련있는 라우터를 조직화(묶음)하거나 깊게 중첩된 라우트 파일 이름 길이를 단순화시킬 수 있다. |
Mixed Flat and Directory Routes | - 중첩된 라우트를 표현하면서 단일 배열의 단순성을 유지할 수 있다. |
Code-Based Routes | - 코드 내에서 동적으로 라우트를 정의하는 방식이다. |
Case-Sensitivity | - 경로의 대소문자 구분을 설정할 수 있는 기능이다. |
가장 최상위 라우트로, 다른 모든 라우트의 기준이 되는 라우트이다.Root Route
는 아래와 같은 특징이 존재한다.
Root Route
는 경로가 없지만 다른 라우트들과 동일한 기능에 접근할 수 있습니다. 예를 들어, 일관된 UI나 상태에 따른 처리 (컴포넌트나 로더, 검색 매개변수의 유효성 검사 등)가 가능합니다.
import { createRootRoute ] from "@tanstack/react-router";
// 가장 최상위 라우트, 전체 라우터 구조 정의
const rootRoute = createRootRoute(); // 루트 라우트 생성
// context 주입 라우트, 전체 라우터에 공통된 상태나 데이터를 전달
const contextRoute = createRootRouteWithContext<MyContext>(); // 의존성 주입
Root Route
를 제외한 모든 라우트는 FileRoute
클래스를 기반으로 구성된다. FileRoute
는 파일 기반 라우팅을 사용할 때, 타입 안전성을 제공하는 Route
클래스의 래퍼 클래스이다. createFileRoute(path :string)
메서드를 사용하여 라우트를 생성한다.
import { createFileRoute } from '@tanstack/react-router'
// 파일 기반 라우트 생성
export const Route = createFileRoute('/profile')({
component: ProfileComponent,
})
정적 라우트는 특정 경로와 완전히 일치하는 경우에만 매칭이 되는 라우트이다. 간단하고 직관적이다.
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/about')({
component: AboutComponent,
})
function AboutComponent() {
return <div>About</div>
}
인덱스 라우트는 부모 라우트가 정확히 매칭되고 자식 라우트가 매칭되지 않았을 때 동작하는 라우트이다. 파일 이름 끝에 index.tsx
를 붙여 사용한다. (ex. filename.index.tsx
)
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/')({
component: PostsIndexComponent,
})
function PostsIndexComponent() {
return <div>Please select a post!</div>
}
$lable
과 같은 형태로 동작하며, params
객체에 담아 애플리케이션에서 사용한다.
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
// In a loader
loader: ({ params }) => fetchPost(params.postId),
// Or in a component
component: PostComponent,
})
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post ID: {postId}</div>
}
$
를 splat이라고 부른다. URL 경로에서 $
부터 끝의 문자열까지 params
의 \_splat
으로 접근하여 사용할 수 있다. (Why use $
? 파일 이름이나 CLI 도구와의 호환성 문제로 인해 $
를 사용하여 처리한다.)
:D Pathless / Layout Routes
_언더스코어로 시작하는 경우, 이를 Pathless / Layout Routes라고 한다. 경로에 직접 매칭되지 않고 다른 컴포넌트를 감싸는 용도로 사용된다. 전체 레이아웃을 정의하거나 공통된 UI 컴포넌트를 제공하는 데 사용된다. (로더나 에러 핸들링 등 서비스 내 공통으로 처리되어야 하는 부분) 파일 이름의 끝에 _layout.tsx를 붙여 표현한다.
레이아웃을 일관되게 유지하고, 자식 페이지에 공통된 설정이나 스타일을 적용하는 데 유용하다.
import { Outlet, createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_layout')({
component: LayoutComponent,
})
function LayoutComponent() {
return (
<div>
<h1>Layout</h1>
<Outlet />
</div>
)
}
특정 부모 라우트와 별도로, 동일한 경로 패턴을 갖지만 독립적으로 작동하는 라우트를 만들 때 사용한다. 일반적으로 라우트는 부모와 자식 관계를 가지지만, 비중첩 라우트는 부모 경로에서 "break out"하여 완전히 다른 컴포넌트 트리를 렌더링 할 수 있다. 부모 파일 이름 뒤에 \_
언더 스코어를 붙여 표현한다.
// `posts_.$postId.edit.tsx`
export const EditRoute = createFileRoute('/posts/$postId/edit')({
component: EditPost,
});
function EditPost() {
const { postId } = Route.useParams();
return <div>편집 중인 게시물 ID: {postId}</div>;
}
// `posts.$postId.tsx`
export const PostRoute = createFileRoute('/posts/$postId')({
component: PostDetail,
});
function PostDetail() {
const { postId } = Route.useParams();
return <div>게시물 ID: {postId}</div>;
}
요청한 URL이 어떤 라우트와도 일치하지 않는 경우를 표현한다. NotFoundRoute
는 라우트 트리에 포함되면 라우트가 제대로 동작하지 않기 때문에 포함시키지 않도록 한다. 또한, path
와 id
를 가지지 않고 경로 파라미터를 파싱하거나 검증할 수 없다는 특징이 있다. 라우트 유효성이 어긋나거나 잘못된 경로를 요청했을 때 발생한다.