찾을 수 없음 오류
⚠️ 이 페이지에서는 찾을 수 없음 오류를 처리하는 새로운
notFound함수와notFoundComponentAPI를 다룹니다.NotFoundRoute라우트는 지원 중단 예정이며 향후 릴리스에서 제거됩니다. 자세한 내용은NotFoundRoute에서 마이그레이션을 참고합니다.
개요
TanStack Router에서 찾을 수 없음 오류는 다음 두 가지 경우에 사용합니다.
- 매치되지 않는 라우트 경로: 경로가 알려진 라우트 매칭 패턴과 일치하지 않거나, 라우트와 부분적으로 일치하지만 추가 경로 세그먼트가 있는 경우입니다.
- 경로가 알려진 라우트 매칭 패턴과 일치하지 않으면 라우터가 자동으로 찾을 수 없음 오류를 발생시킵니다.
- 라우터의
notFoundMode가fuzzy로 설정되면notFoundComponent가 있는 가장 가까운 매치 라우트가 오류를 처리합니다. 라우터의notFoundMode가root로 설정되면 루트 라우트가 오류를 처리합니다. - 예시:
/users라우트가 없는데/users에 액세스하는 경우- 라우트 트리가
/posts/$postId만 처리하는데/posts/1/edit에 액세스하는 경우
- 누락된 리소스: 지정한 ID의 게시물이나 사용할 수 없거나 존재하지 않는 비동기 데이터처럼 리소스를 찾을 수 없는 경우입니다.
- 리소스를 찾을 수 없으면 개발자가 찾을 수 없음 오류를 발생시켜야 합니다.
notFound유틸리티를 사용해beforeLoad또는loader함수에서 처리할 수 있습니다. notFoundComponent가 있는 가장 가까운 매치 라우트(loader내부에서notFound를 호출한 경우) 또는 루트 라우트가 처리합니다.- 예시:
- ID가 1인 게시물이 존재하지 않는데
/posts/1에 액세스하는 경우 - 문서가 존재하지 않는데
/docs/path/to/document에 액세스하는 경우
- ID가 1인 게시물이 존재하지 않는데
- 리소스를 찾을 수 없으면 개발자가 찾을 수 없음 오류를 발생시켜야 합니다.
내부적으로 이 두 경우는 동일한 notFound 함수와 notFoundComponent API를 사용해 구현됩니다.
notFoundMode 옵션
TanStack Router가 알려진 라우트 패턴과 일치하지 않거나 라우트 패턴과 부분적으로 일치하지만 뒤에 pathname 세그먼트가 추가된 pathname을 만나면 자동으로 찾을 수 없음 오류를 발생시킵니다.
라우터는 notFoundMode 옵션에 따라 이러한 자동 오류를 다르게 처리합니다.
- "fuzzy" 모드(기본값): 라우터가 가장 가까운 적합한 매치 라우트를 지능적으로 찾아
notFoundComponent를 표시합니다. - "root" 모드: 가장 가까운 매치 라우트와 관계없이 모든 찾을 수 없음 오류를 루트 라우트의
notFoundComponent가 처리합니다.
notFoundMode: 'fuzzy'
기본적으로 라우터의 notFoundMode는 fuzzy로 설정됩니다. 이는 pathname이 알려진 라우트와 일치하지 않을 때 라우터가 notFoundComponent가 구성된 가장 가까운 매치 라우트를 사용하려고 시도한다는 의미입니다.
❓ 기본값인 이유는 무엇인가요? 퍼지 매칭은 가능한 한 많은 부모 레이아웃을 보존하므로, 사용자가 도착하리라 생각한 위치를 바탕으로 유용한 위치로 탐색할 수 있는 더 많은 맥락을 제공합니다.
가장 가까운 적합한 라우트는 다음 기준으로 찾습니다.
- 라우트에
notFoundComponent가 구성되어 있거나 라우터에defaultNotFoundComponent가 구성되어 있어야 합니다.
예를 들어 다음 라우트 트리를 살펴봅니다.
__root__(notFoundComponent가 구성됨)posts(notFoundComponent가 구성됨)$postId(notFoundComponent가 구성됨)
/posts/1/edit 경로가 제공되면 다음 컴포넌트 구조가 렌더링됩니다.
<Root><Posts><Post><Post.notFoundComponent>
$postId 라우트의 notFoundComponent가 notFoundComponent가 구성된 가장 가까운 매치 라우트이므로 렌더링됩니다.
notFoundMode: 'root'
notFoundMode가 root로 설정되면 모든 찾을 수 없음 오류를 가장 가까운 퍼지 매치 라우트에서 버블링하는 대신 루트 라우트의 notFoundComponent가 처리합니다.
예를 들어 다음 라우트 트리를 살펴봅니다.
__root__(notFoundComponent가 구성됨)posts(notFoundComponent가 구성됨)$postId(notFoundComponent가 구성됨)
/posts/1/edit 경로가 제공되면 다음 컴포넌트 구조가 렌더링됩니다.
<Root><Root.notFoundComponent>
notFoundMode가 root로 설정되어 있으므로 __root__ 라우트의 notFoundComponent가 렌더링됩니다.
라우트의 notFoundComponent 구성
두 유형의 찾을 수 없음 오류를 처리하려면 라우트에 notFoundComponent를 연결할 수 있습니다. 찾을 수 없음 오류가 발생하면 이 컴포넌트가 렌더링됩니다.
예를 들어 존재하지 않는 설정 페이지를 처리하도록 /settings 라우트에 notFoundComponent를 구성합니다.
export const Route = createFileRoute('/settings')({
component: () => {
return (
<div>
<p>Settings page</p>
<Outlet />
</div>
)
},
notFoundComponent: () => {
return <p>This setting page doesn't exist!</p>
},
})
또는 존재하지 않는 게시물을 처리하도록 /posts/$postId 라우트에 notFoundComponent를 구성합니다.
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => {
const post = await getPost(postId)
if (!post) throw notFound()
return { post }
},
component: ({ post }) => {
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
)
},
notFoundComponent: () => {
return <p>Post not found!</p>
},
})
라우터 전체의 기본 찾을 수 없음 처리
자식 라우트가 있는 애플리케이션의 모든 라우트에 기본 찾을 수 없음 컴포넌트를 제공할 수 있습니다.
자식이 있는 라우트만 해당하는 이유는 무엇인가요? 리프 노드 라우트(자식이 없는 라우트)는
Outlet을 렌더링하지 않으므로 찾을 수 없음 오류를 처리할 수 없습니다.
이렇게 하려면 createRouter 함수에 defaultNotFoundComponent를 전달합니다.
const router = createRouter({
defaultNotFoundComponent: () => {
return (
<div>
<p>Not found!</p>
<Link to="/">Go home</Link>
</div>
)
},
})
직접 notFound 오류 발생시키기
notFound 함수를 사용해 로더 메서드와 컴포넌트에서 찾을 수 없음 오류를 수동으로 발생시킬 수 있습니다. 리소스를 찾을 수 없음을 알려야 할 때 유용합니다.
notFound 함수는 redirect 함수와 비슷하게 작동합니다. 찾을 수 없음 오류를 발생시키려면 notFound()를 throw할 수 있습니다.
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => {
// Returns `null` if the post doesn't exist
const post = await getPost(postId)
if (!post) {
throw notFound()
// Alternatively, you can make the notFound function throw:
// notFound({ throw: true })
}
// Post is guaranteed to be defined here because we threw an error
return { post }
},
})
위의 찾을 수 없음 오류는 notFoundComponent 라우트 옵션 또는 defaultNotFoundComponent 라우터 옵션이 구성된 동일 라우트나 가장 가까운 부모 라우트가 처리합니다.
오류를 처리할 라우트나 적합한 부모 라우트를 찾지 못하면 루트 라우트가 TanStack Router의 매우 기본적이고 의도적으로 바람직하지 않은 기본 찾을 수 없음 컴포넌트를 사용해 처리합니다. 이 컴포넌트는 단순히 <p>Not Found</p>를 렌더링합니다. 찾을 수 없음 오류를 처리하도록 루트 라우트에 notFoundComponent를 하나 이상 연결하거나 라우터 전체에 defaultNotFoundComponent를 구성하는 것을 강력히 권장합니다.
⚠️
beforeLoad에서notFound()를 throw하면 TanStack Router는 다른 찾을 수 없음 오류와 같은 방식으로 이를 확인합니다.
routeId를 전달하면 해당 라우트(또는 가장 가까운 유효한 조상 경계)가 처리합니다.routeId를 전달하지 않으면notFoundComponent가 있는 가장 가까운 라우트/조상이 처리합니다(라우터의 모드와 매칭 규칙에 따름).- 적합한 경계를 찾지 못하면 루트/기본 찾을 수 없음 동작으로 처리합니다.
beforeLoad에서 발생시킨 찾을 수 없음 오류의 경우에도 TanStack Router는 선택된 찾을 수 없음 경계가 필요한 로더 데이터와 함께 렌더링될 수 있도록 필요한 부모 로더를 실행합니다.
찾을 수 없음 오류를 처리할 라우트 지정
때로는 특정 부모 라우트에서 찾을 수 없음 처리를 시작하고 일반적인 찾을 수 없음 컴포넌트 전파를 우회할 수 있습니다. 이렇게 하려면 notFound 함수의 route 옵션에 라우트 ID를 전달합니다.
// _pathlessLayout.tsx
export const Route = createFileRoute('/_pathlessLayout')({
// This will render
notFoundComponent: () => {
return <p>Not found (in _pathlessLayout)</p>
},
component: () => {
return (
<div>
<p>This is a pathless layout route!</p>
<Outlet />
</div>
)
},
})
// _pathlessLayout/route-a.tsx
export const Route = createFileRoute('/_pathless/route-a')({
loader: async () => {
// This will make LayoutRoute handle the not-found error
throw notFound({ routeId: '/_pathlessLayout' })
// ^^^^^^^^^ This will autocomplete from the registered router
},
// This WILL NOT render
notFoundComponent: () => {
return <p>Not found (in _pathlessLayout/route-a)</p>
},
})
루트 라우트를 수동으로 지정
notFound 함수의 route 속성에 내보낸 rootRouteId 변수를 전달해 루트 라우트를 지정할 수도 있습니다.
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => {
const post = await getPost(postId)
if (!post) throw notFound({ routeId: rootRouteId })
return { post }
},
})
컴포넌트에서 찾을 수 없음 오류 발생시키기
컴포넌트에서도 찾을 수 없음 오류를 발생시킬 수 있습니다. 하지만 로더 데이터를 올바르게 타입 지정하고 깜박임을 방지하려면 컴포넌트 대신 로더 메서드에서 찾을 수 없음 오류를 발생시키는 것을 권장합니다.
TanStack Router는 CatchBoundary와 유사한 CatchNotFound 컴포넌트를 제공합니다. 이를 사용해 컴포넌트에서 찾을 수 없음 오류를 포착하고 그에 맞는 UI를 표시할 수 있습니다.
notFoundComponent 내부의 데이터 로딩
데이터 로딩에서 notFoundComponent는 특수한 경우입니다. 액세스하려는 라우트와 찾을 수 없음 오류가 발생한 위치에 따라 SomeRoute.useLoaderData가 정의되지 않을 수 있습니다. 하지만 Route.useParams, Route.useSearch, Route.useRouteContext 등은 정의된 값을 반환합니다.
불완전한 로더 데이터를 notFoundComponent에 전달해야 한다면 notFound 함수의 data 옵션을 통해 데이터를 전달하고 notFoundComponent에서 검증합니다.
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params: { postId } }) => {
const post = await getPost(postId)
if (!post)
throw notFound({
// Forward some data to the notFoundComponent
// data: someIncompleteLoaderData
})
return { post }
},
// `data: unknown` is passed to the component via the `data` option when calling `notFound`
notFoundComponent: ({ data }) => {
// ❌ useLoaderData is not valid here: const { post } = Route.useLoaderData()
// ✅:
const { postId } = Route.useParams()
const search = Route.useSearch()
const context = Route.useRouteContext()
return <p>Post with id {postId} not found!</p>
},
})
SSR과 함께 사용
자세한 내용은 SSR 가이드를 참고합니다.
NotFoundRoute에서 마이그레이션
NotFoundRoute API는 notFoundComponent를 사용하는 방식으로 지원 중단 예정입니다. NotFoundRoute API는 향후 릴리스에서 제거됩니다.
NotFoundRoute를 사용하면 notFound 함수와 notFoundComponent가 작동하지 않습니다.
주요 차이점은 다음과 같습니다.
NotFoundRoute는 렌더링하려면 부모 라우트에<Outlet>이 필요한 라우트입니다.notFoundComponent는 모든 라우트에 연결할 수 있는 컴포넌트입니다.NotFoundRoute를 사용하면 레이아웃을 사용할 수 없습니다.notFoundComponent는 레이아웃과 함께 사용할 수 있습니다.notFoundComponent를 사용하면 경로 매칭이 엄격합니다. 즉/post/$postId라우트가 있을 때/post/1/2/3에 액세스하면 찾을 수 없음 오류가 발생합니다.NotFoundRoute를 사용하면/post/1/2/3이NotFoundRoute와 일치하고<Outlet>이 있을 때만 렌더링됩니다.
NotFoundRoute에서 notFoundComponent로 마이그레이션하려면 몇 가지 변경만 하면 됩니다.
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen.'
- import { notFoundRoute } from './notFoundRoute' // [!code --]
export const router = createRouter({
routeTree,
- notFoundRoute // [!code --]
})
// routes/__root.tsx
import { createRootRoute } from '@tanstack/react-router'
export const Route = createRootRoute({
// ...
+ notFoundComponent: () => { // [!code ++]
+ return <p>Not found!</p> // [!code ++]
+ } // [!code ++]
})
중요한 변경 사항은 다음과 같습니다.
- 전역 찾을 수 없음 처리를 위해 루트 라우트에
notFoundComponent를 추가합니다.- 라우트 트리의 다른 라우트에도
notFoundComponent를 추가해 해당 라우트의 찾을 수 없음 오류를 처리할 수 있습니다.
- 라우트 트리의 다른 라우트에도
notFoundComponent는<Outlet>렌더링을 지원하지 않습니다.