TanStack Start v1에서 URL의 로케일 매개변수를 검증하는 방법
지원되지 않는 로케일 코드를 우아하게 처리하기
문제
언어 코드가 URL 구조의 일부가 되면 검증이 필요한 사용자 입력으로 변환됩니다. 사용자는 /en/about나 /fr/contact와 같은 유효한 코드만큼 쉽게 /xx/about, /gibberish/contact, 또는 /typo123/products와 같은 임의의 문자열을 로케일 세그먼트에 수동으로 입력할 수 있습니다. 검증 없이는 애플리케이션이 존재하지 않는 로케일에 대한 번역을 로드하려 시도하거나, 손상된 콘텐츠를 표시하거나, 충돌할 수 있습니다. 각각의 유효하지 않은 로케일은 사용자가 복구하거나 작동하는 페이지로 이동할 수 없는 잠재적인 막다른 길을 나타냅니다.
검증되지 않은 로케일 매개변수는 예측할 수 없는 동작을 생성합니다. 애플리케이션은 번역 로드에 자동으로 실패하거나, 폴백과 누락된 콘텐츠가 혼합된 상태로 렌더링하거나, 번역 키에 액세스할 때 런타임 오류를 발생시킬 수 있습니다. 손상된 링크를 따라가거나 URL을 잘못 입력한 사용자는 무엇이 잘못되었는지 또는 어떻게 수정해야 하는지에 대한 명확한 피드백 없이 방치됩니다.
해결책
라우트의 beforeLoad 함수에서 URL의 로케일 매개변수를 지원되는 로케일 목록과 대조하여 검증하세요. 로케일이 유효하지 않거나 누락된 경우, 사용자를 기본 로케일이 포함된 유효한 URL로 리디렉션하거나 not-found 오류를 발생시켜 유용한 오류 페이지를 표시하세요. 이를 통해 지원되는 로케일만 처리되고 사용자가 항상 유효하고 번역 가능한 페이지에 도달하도록 보장합니다.
beforeLoad 함수는 라우트가 로드되기 전에 실행되므로 로케일을 확인하기에 이상적인 위치입니다. redirect() 또는 notFound() 오류를 발생시킴으로써 유효하지 않은 로케일로 라우트가 렌더링되는 것을 방지하고 사용자를 작동하는 상태로 안내할 수 있습니다.
단계
1. 지원되는 로케일 정의
유효한 로케일 코드의 상수 배열과 타입 안전 검증 함수를 생성합니다.
const SUPPORTED_LOCALES = ["en", "fr", "es", "de"] as const;
type Locale = (typeof SUPPORTED_LOCALES)[number];
function isValidLocale(locale: string | undefined): locale is Locale {
return SUPPORTED_LOCALES.includes(locale as Locale);
}
이는 지원되는 로케일에 대한 단일 정보 소스와 TypeScript가 이해할 수 있는 재사용 가능한 검증 함수를 제공합니다.
2. 로케일 검증이 포함된 레이아웃 라우트 생성
선택적 로케일 매개변수를 사용하고 beforeLoad에서 검증하세요.
import { createFileRoute, redirect } from "@tanstack/react-router";
const DEFAULT_LOCALE: Locale = "en";
export const Route = createFileRoute("/{-$locale}")({
beforeLoad: ({ params }) => {
const { locale } = params;
if (locale && !isValidLocale(locale)) {
throw redirect({
to: "/{-$locale}",
params: { locale: undefined },
replace: true,
});
}
return {
locale: (locale as Locale) || DEFAULT_LOCALE,
};
},
});
beforeLoad 함수는 로케일 매개변수를 확인합니다. 매개변수가 존재하지만 유효하지 않은 경우, 사용자는 로케일 접두사가 없는 동일한 경로로 리디렉션되며, 이는 기본 로케일로 해석됩니다. 검증된 로케일은 하위 라우트에서 사용할 수 있도록 컨텍스트에 반환됩니다.
3. 중첩된 라우트에서 로케일 검증
로케일이 필요한 라우트의 경우, 유효성을 검사하고 유효하지 않으면 notFound()를 발생시킵니다.
import { createFileRoute, notFound } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}/products")({
beforeLoad: ({ params }) => {
const { locale } = params;
if (locale && !isValidLocale(locale)) {
throw notFound();
}
return {
locale: (locale as Locale) || DEFAULT_LOCALE,
};
},
component: ProductsPage,
});
function ProductsPage() {
const { locale } = Route.useRouteContext();
return <div>Products in {locale}</div>;
}
이 접근 방식은 유효하지 않은 로케일에 대해 리디렉션하는 대신 not-found 페이지를 표시하며, 이는 URL이 잘못 형성되었음을 알리고자 할 때 유용합니다.
4. 유효하지 않은 로케일에 대한 not-found 컴포넌트 추가
루트 라우트에 notFoundComponent를 정의하여 유효하지 않은 로케일 오류를 적절하게 처리합니다.
import { createRootRoute } from "@tanstack/react-router";
export const Route = createRootRoute({
notFoundComponent: () => {
return (
<div>
<h1>Page Not Found</h1>
<p>The language or page you requested does not exist.</p>
<a href="/">Go to home page</a>
</div>
);
},
});
이 컴포넌트는 beforeLoad에서 notFound()가 발생했을 때 렌더링되어 사용자에게 명확한 메시지와 유효한 페이지로 돌아갈 수 있는 방법을 제공합니다.