Next.js(Pages Router) v16에서 URL의 로케일 매개변수를 검증하는 방법
지원되지 않는 로케일 코드를 우아하게 처리하기
문제
로케일 코드가 URL 구조의 일부가 되면 검증이 필요한 사용자 입력으로 변환됩니다. 방문자는 /en/about와 같은 유효한 로케일만큼 쉽게 /xx/about 또는 /gibberish/contact를 입력할 수 있습니다. 검증이 없으면 애플리케이션이 충돌하거나, 손상된 콘텐츠를 표시하거나, 혼란스러운 오류 메시지를 표시할 수 있습니다. 잘못된 로케일 URL을 접하는 사용자는 유효한 로케일로의 리디렉션이나 무엇이 잘못되었는지 이해하는 데 도움이 되는 적절한 "Not Found" 응답을 통해 명확한 경로가 필요합니다.
해결 방법
요청이 페이지 컴포넌트에 도달하기 전에 지원되는 로케일 목록에 대해 들어오는 로케일 매개변수를 검증합니다. Next.js 미들웨어를 사용하여 요청을 가로채고, URL의 로케일이 지원되는 값과 일치하는지 확인하고, 적절하게 응답합니다. 잘못된 로케일의 경우 사용자를 기본 로케일로 리디렉션하거나 요청을 재작성하여 404 페이지를 표시합니다. 이를 통해 유효한 로케일 코드만 콘텐츠 렌더링을 진행하고, 잘못된 코드는 사용자 경험을 손상시키지 않고 우아하게 처리됩니다.
단계
1. Next.js 구성에서 지원되는 로케일 정의
next.config.js에서 i18n 설정을 구성하여 애플리케이션이 지원하는 로케일과 기본값으로 사용할 로케일을 선언합니다.
module.exports = {
i18n: {
locales: ["en", "fr", "de"],
defaultLocale: "en",
localeDetection: false,
},
};
localeDetection를 false로 설정하면 브라우저 기본 설정에 따른 자동 리디렉션이 방지되어 로케일 처리를 완전히 제어할 수 있습니다.
2. 로케일 매개변수를 검증하는 미들웨어 생성
프로젝트 루트 또는 src 폴더를 사용하는 경우 해당 폴더 내에 middleware.ts 파일을 생성합니다.
import { NextRequest, NextResponse } from "next/server";
const SUPPORTED_LOCALES = ["en", "fr", "de"];
const DEFAULT_LOCALE = "en";
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = SUPPORTED_LOCALES.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
);
if (!pathnameHasLocale) {
return;
}
const localeInPath = pathname.split("/")[1];
if (!SUPPORTED_LOCALES.includes(localeInPath)) {
const url = request.nextUrl.clone();
url.pathname = pathname.replace(`/${localeInPath}`, `/${DEFAULT_LOCALE}`);
return NextResponse.redirect(url);
}
}
export const config = {
matcher: ["/((?!_next|api|favicon.ico|.*\\..*).*)"],
};
미들웨어는 URL 경로에서 로케일을 추출하고, 지원되는 로케일 배열과 비교한 후, 유효하지 않은 로케일을 기본 로케일로 리디렉션하면서 나머지 경로는 유지합니다.
3. 404 응답으로 유효하지 않은 로케일 처리하기
리디렉션 대신 404 페이지를 표시하려면, 요청을 커스텀 404 페이지로 재작성하세요.
import { NextRequest, NextResponse } from "next/server";
const SUPPORTED_LOCALES = ["en", "fr", "de"];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = SUPPORTED_LOCALES.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
);
if (!pathnameHasLocale) {
return;
}
const localeInPath = pathname.split("/")[1];
if (!SUPPORTED_LOCALES.includes(localeInPath)) {
const url = request.nextUrl.clone();
url.pathname = "/404";
return NextResponse.rewrite(url);
}
}
export const config = {
matcher: ["/((?!_next|api|favicon.ico|.*\\..*).*)"],
};
빌드 시 정적으로 생성되는 pages/404.js에 커스텀 404 페이지를 생성합니다.
4. 커스텀 404 페이지 생성하기
export default function Custom404() {
return (
<div>
<h1>404 - Page Not Found</h1>
<p>The page you are looking for does not exist.</p>
</div>
);
}
이 페이지는 미들웨어가 유효하지 않은 로케일 요청을 재작성할 때 표시되며, 사용자에게 요청한 URL을 사용할 수 없다는 명확한 메시지를 제공합니다.