지원되지 않는 언어 코드 처리하기
문제
애플리케이션이 URL 경로(예: /en/, /fr/)를 사용하여 언어를 결정하지만, 사용자는 /xx/about과 같은 값을 수동으로 입력할 수 있습니다. 이 값이 지원되는 언어와 일치하지 않으면 애플리케이션이 충돌하거나, 일반적인 오류를 표시하거나, 번역되지 않은 콘텐츠를 표시하여 사용자를 유효한 경험으로 안내하지 못할 수 있습니다.
해결책
모든 수신 요청을 가로채는 미들웨어를 사용합니다. 이 미들웨어는 URL의 언어 코드를 지원되는 언어의 명확한 목록과 비교하여 검증합니다. 코드가 지원되지 않는 경우, 요청이 애플리케이션 로직에 도달하기 전에 "찾을 수 없음" 페이지로 재작성됩니다.
단계
1. 지원되는 언어 정의하기
유효한 언어 코드(로케일) 목록을 저장할 중앙 구성 파일을 만듭니다. 이렇게 하면 미들웨어와 앱의 다른 부분에서 목록을 재사용할 수 있습니다.
// i18n.config.ts
export const locales = ['en', 'es', 'fr'];
2. 미들웨어 파일 생성하기
프로젝트 루트(또는 src/ 디렉토리)에 middleware.ts라는 새 파일을 생성합니다. Next.js는 이 파일을 자동으로 감지하고 요청에서 실행합니다.
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { locales } from './i18n.config';
export function middleware(request: NextRequest) {
// 다음 단계에서 로직이 여기에 들어갑니다
}
3. 유효성 검사 로직 추가하기
middleware 함수 내에서 요청에서 pathname을 가져옵니다. 경로의 첫 번째 세그먼트(예: /en/about에서 en)를 확인하고 유효하고 지원되는 언어인지 확인해야 합니다.
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { locales } from './i18n.config';
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. 루트 경로를 별도로 처리합니다
// (이것은 다음 레시피에서 처리됩니다: "사용자의 선호 언어 감지").
// 지금은 그냥 통과시킵니다.
if (pathname === '/') {
return NextResponse.next();
}
// 2. 경로에서 언어 코드 추출
const langCode = pathname.split('/')[1];
// 3. 언어 코드가 목록에 있는지 확인
if (locales.includes(langCode)) {
// 언어가 유효하면 요청된 페이지로 계속 진행
return NextResponse.next();
}
// 4. 언어가 유효하지 않으면 404 페이지로 재작성
// 이렇게 하면 브라우저 주소창에 유효하지 않은 URL이 유지됩니다
const url = request.nextUrl.clone();
url.pathname = `/404`; // app/404.tsx 파일이 있다고 가정
return NextResponse.rewrite(url);
}
이 로직은 모든 요청을 확인합니다. URL이 /fr/about인 경우, langCode는 fr이고, locales에서 찾아지면 요청이 계속됩니다. URL이 /xx/about인 경우, langCode는 xx이고, 찾아지지 않으면 앱이 유효하지 않은 요청을 처리하려고 시도하지 않고 사용자에게 404 페이지가 표시됩니다.
4. 미들웨어 매처 구성하기
미들웨어를 더 효율적으로 만들기 위해, 어떤 경로에서 실행할지 지정해야 합니다. 페이지 요청에서는 실행되지만 정적 파일과 API 라우트에서는 건너뛰도록 하고 싶습니다.
middleware.ts 파일 하단에 config 객체를 추가하세요.
// middleware.ts
// ... (위에서 작성한 미들웨어 함수)
export const config = {
matcher: [
// 다음으로 시작하는 모든 경로 건너뛰기:
// - api (API 라우트)
// - _next/static (정적 파일)
// - _next/image (이미지 최적화 파일)
// - favicon.ico (파비콘 파일)
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
이 정규식은 일반적으로 정적 에셋이나 API 호출을 위한 경로를 제외한 모든 경로에서 미들웨어를 실행하도록 지시합니다. 이렇게 하면 모든 이미지, 폰트 또는 데이터 요청에 불필요한 유효성 검사가 실행되는 것을 방지할 수 있습니다.