사용자의 선호 언어 감지하기

새로운 방문자를 가장 적합한 언어로 리다이렉트

문제

사용자가 애플리케이션의 루트(예: /)에 처음 방문할 때, 영어와 같은 기본 언어가 표시됩니다. 이는 다른 언어를 사용하는 사용자들에게 즉각적인 불편함을 초래하며, 브라우저가 이미 그들의 선호도를 전달하고 있음에도 불구하고 수동으로 언어 전환기를 찾도록 강요합니다.

해결책

루트 경로(/)에 대한 요청을 가로채는 미들웨어를 사용합니다. 사용자의 Accept-Language HTTP 헤더를 확인하여 선호하는 언어를 찾습니다. 해당 언어가 애플리케이션에서 지원된다면, 사용자를 해당 언어의 루트(예: /fr)로 리디렉션합니다. 지원되지 않는다면, 기본 언어(예: /en)로 리디렉션합니다.

단계

1. 언어 파서 설치

Accept-Language 헤더는 복잡할 수 있습니다(예: fr-CH, fr;q=0.9, en;q=0.8). 작은 라이브러리가 이 헤더를 파싱하고 지원하는 언어 목록에서 최적의 일치를 찾는 데 도움이 됩니다.

터미널에서 다음 명령을 실행하세요:

npm install accept-language-parser

2. 언어 및 기본값 정의

지원하는 언어 목록을 저장하고 기본값을 정의하는 중앙 구성 파일을 생성합니다. 이 기본값은 사용자의 브라우저 환경설정이 지원하는 언어와 일치하지 않을 때 사용됩니다.

// i18n.config.ts

export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';

3. 미들웨어 생성

프로젝트 루트에 middleware.ts 파일을 생성합니다. 이 파일은 들어오는 요청에서 실행되어 경로와 헤더를 확인할 수 있게 합니다.

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import parser from 'accept-language-parser';
import { locales, defaultLocale } from './i18n.config';

// 최적의 언어 일치를 찾는 헬퍼 함수
function getBestLocale(acceptLangHeader: string | null) {
  if (!acceptLangHeader) {
    return defaultLocale;
  }

  // 파서를 사용하여 최적의 지원 언어 찾기
  const bestMatch = parser.pick(locales, acceptLangHeader, {
    loose: true,
  });

  return bestMatch || defaultLocale;
}

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // 1. 요청이 루트 경로인지 확인
  if (pathname === '/') {
    // 사용자의 선호 언어 가져오기
    const acceptLang = request.headers.get('Accept-Language');
    const bestLocale = getBestLocale(acceptLang);

    // 최적으로 일치하는 언어 경로로 리디렉션
    request.nextUrl.pathname = `/${bestLocale}`;
    return NextResponse.redirect(request.nextUrl);
  }

  // 2. 다른 모든 경로에 대해서는 정상적으로 계속 진행
  return NextResponse.next();
}

export const config = {
  matcher: [
    // 다음으로 시작하는 모든 경로 건너뛰기:
    // - api (API 라우트)
    // - _next/static (정적 파일)
    // - _next/image (이미지 최적화 파일)
    // - favicon.ico (파비콘 파일)
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
};

이 코드는 루트 경로(/)에 대해서만 로직을 실행합니다. 사용자가 /를 방문하면 Accept-Language 헤더를 확인하고 최적의 일치(예: es)를 찾아 /es로 리디렉션합니다. /en/about과 같은 다른 모든 요청은 이 로직에 의해 무시되고 그대로 통과합니다.