Next.js(Pages Router) v16에서 사용자 언어 기본 설정을 감지하는 방법

브라우저 기본 설정을 기반으로 자동 리디렉션

문제

모든 브라우저는 각 HTTP 요청과 함께 Accept-Language 헤더를 전송하여 사용자가 선호하는 언어를 우선순위 순서로 나타냅니다. 대부분의 애플리케이션은 이 귀중한 신호를 무시하고 모든 방문자에게 기본 언어를 제공하여, 애플리케이션이 이미 사용자의 기본 설정을 알고 있음에도 불구하고 사용자가 수동으로 언어 전환기를 찾도록 강요합니다. 이는 첫 방문 시 불필요한 마찰을 일으키고 사용자가 자신의 언어로 된 콘텐츠를 찾기 전에 사이트를 떠나게 만들 수 있습니다.

사용자가 애플리케이션의 루트 경로에 도착하면 언어 기본 설정을 확인하고 즉시 이해할 수 있는 언어로 된 콘텐츠로 안내할 수 있는 기회가 있습니다. 이러한 감지가 없으면 국제 사용자는 브라우저 설정과 관계없이 영어 우선 경험을 하게 되어 환영받는 현지화된 첫인상을 제공할 기회를 놓치게 됩니다.

솔루션

루트 경로에 대한 모든 요청에서 서버 측 로직을 실행하는 루트 페이지를 생성합니다. 수신 요청에서 Accept-Language HTTP 헤더를 읽고 파싱하여 사용자가 가장 선호하는 언어를 추출합니다. 이 언어를 애플리케이션이 지원하는 언어 목록과 비교합니다. 일치하는 항목이 발견되면 사용자를 해당 언어의 루트 경로로 리디렉션합니다. 지원되는 언어가 일치하지 않으면 기본 언어 경로로 리디렉션합니다.

이 접근 방식은 각 요청마다 서버에서 실행되며 리디렉션 응답을 반환할 수 있는 Next.js의 getServerSideProps 함수를 활용합니다. 루트 경로에서 감지를 처리함으로써 애플리케이션은 지능적인 기본값을 제공하면서도 필요한 경우 사용자가 나중에 수동으로 언어를 전환할 수 있도록 합니다.

단계

1. Accept-Language 헤더를 파싱할 라이브러리 설치

Accept-Language 헤더에는 선택적 품질 값이 포함된 쉼표로 구분된 언어 코드 목록이 포함되어 있으며 이를 파싱해야 합니다. 이 형식을 처리할 파서 라이브러리를 설치하세요.

npm install accept-language-parser

이 라이브러리는 헤더 문자열에서 언어 코드와 품질 점수를 추출하여 우선순위 순서로 반환합니다.

2. 서버 측 리디렉션 로직이 있는 루트 페이지 생성

루트 디렉터리로 자동 라우팅될 pages/index.tsx 파일을 생성합니다. getServerSideProps를 사용하여 대상과 영구 플래그가 포함된 리디렉션 객체를 반환합니다.

import { GetServerSideProps } from "next";
import parser from "accept-language-parser";

const SUPPORTED_LOCALES = ["en", "fr", "es", "de"];
const DEFAULT_LOCALE = "en";

export default function RootPage() {
  return null;
}

export const getServerSideProps: GetServerSideProps = async (context) => {
  const acceptLanguageHeader = context.req.headers["accept-language"];

  let targetLocale = DEFAULT_LOCALE;

  if (acceptLanguageHeader) {
    const languages = parser.parse(acceptLanguageHeader);

    const matchedLanguage = languages.find((lang) =>
      SUPPORTED_LOCALES.includes(lang.code),
    );

    if (matchedLanguage) {
      targetLocale = matchedLanguage.code;
    }
  }

  return {
    redirect: {
      destination: `/${targetLocale}`,
      permanent: false,
    },
  };
};

getServerSideProps 함수는 각 요청마다 실행되어 Accept-Language 헤더를 읽고 페이지 콘텐츠가 렌더링되기 전에 적절한 로케일 경로로 리디렉션합니다.

3. 지원되는 로케일 정의

애플리케이션이 지원하는 언어와 일치하도록 SUPPORTED_LOCALES 배열을 업데이트합니다. 파서는 품질 순서대로 언어를 반환하며, 코드는 첫 번째 일치 항목을 선택합니다.

const SUPPORTED_LOCALES = ["en", "fr", "es", "de", "ja", "zh"];
const DEFAULT_LOCALE = "en";

파서는 품질이 높은 순서부터 낮은 순서로 정렬된 언어를 반환하므로, 발견된 첫 번째 지원 언어는 애플리케이션이 충족할 수 있는 사용자의 가장 강력한 선호도를 나타냅니다.

4. Accept-Language 헤더가 없는 경우 처리

일부 요청에는 Accept-Language 헤더가 포함되지 않을 수 있습니다. 코드는 헤더의 존재 여부를 확인하고 헤더가 없을 때 기본 로케일로 폴백합니다.

if (acceptLanguageHeader) {
  const languages = parser.parse(acceptLanguageHeader);

  const matchedLanguage = languages.find((lang) =>
    SUPPORTED_LOCALES.includes(lang.code),
  );

  if (matchedLanguage) {
    targetLocale = matchedLanguage.code;
  }
}

이를 통해 브라우저 언어 정보를 사용할 수 없는 경우에도 애플리케이션이 항상 유효한 로케일 경로로 리디렉션되도록 보장합니다.