Next.js(Pages Router) v16에서 세션 간 언어 선택 기억하기
사용자의 명시적 언어 선택 저장하기
문제
사용자가 명시적으로 언어를 선택할 때, 그 선택은 사용자의 선호도를 반영하며 브라우저 헤더나 지리적 위치에 기반한 자동 감지보다 우선시되어야 합니다. 지속성이 없으면 이러한 선호도는 브라우저가 닫히거나 세션이 종료될 때 손실됩니다. 다음 방문 시 애플리케이션은 새롭게 시작되어 사용자가 다시 언어를 선택해야 합니다. 이러한 반복은 애플리케이션이 사용자 선호도를 존중하지 않는다는 신호를 보내며, 마찰을 일으키고 신뢰를 감소시킵니다.
이 문제는 두 가지입니다: 선택 순간에 사용자의 명시적 선택을 캡처하고, 자동 감지 로직이 실행되기 전에 후속 방문에서 해당 선택을 검색하는 것입니다. 저장된 선호도가 요청 수명 주기 초기에 확인되지 않으면, 사용자는 명시적 선택 대신 브라우저 설정에 따라 리디렉션될 수 있어, 처음부터 선택을 한 가치를 훼손합니다.
해결책
사용자가 명시적으로 언어를 선택할 때 지속적인 쿠키에 해당 선택을 저장합니다. 애플리케이션 루트에 대한 향후 방문 시, 브라우저 기반 로케일 감지로 돌아가기 전에 이 쿠키를 확인합니다. 유효한 저장된 로케일이 발견되면 사용자를 해당 로케일의 루트 경로로 리디렉션하여 선호도가 즉시 존중되도록 합니다.
이 접근 방식은 명시적 사용자 선택과 자동 감지를 분리합니다. 쿠키는 브라우저 재시작 후에도 유지되는 지속적인 의도 신호로 작용하며 Accept-Language 헤더와 같은 일시적 신호보다 우선시됩니다. 초기 요청 중에 서버 측에서 쿠키를 확인함으로써 페이지가 렌더링되기 전에 리디렉션이 발생하여 원활한 경험을 제공합니다.
단계
1. 클라이언트 측에서 로케일 선호도 쿠키를 설정하는 헬퍼 생성
사용자가 언어를 선택하면 세션 간에 지속되는 쿠키에 그들의 선택을 저장합니다.
export function setLocalePreference(locale: string) {
const maxAge = 60 * 60 * 24 * 365;
document.cookie = `NEXT_LOCALE=${locale}; path=/; max-age=${maxAge}; SameSite=Lax`;
}
이 함수는 선택한 로케일로 NEXT_LOCALE이라는 쿠키를 작성하며, 유효 기간은 1년입니다. path=/는 전체 애플리케이션에서 사용 가능하도록 보장하고, SameSite=Lax는 쿠키가 최상위 탐색에서 전송되도록 허용하면서 합리적인 CSRF 보호를 제공합니다.
2. 사용자가 언어를 선택할 때 헬퍼 함수 호출하기
언어 전환기 컴포넌트에 헬퍼를 통합하여 선택 즉시 환경설정이 저장되도록 합니다.
import { useRouter } from "next/router";
import { setLocalePreference } from "@/lib/locale";
export default function LanguageSwitcher() {
const router = useRouter();
const { locales, locale: currentLocale } = router;
const handleLocaleChange = (newLocale: string) => {
setLocalePreference(newLocale);
router.push(router.pathname, router.asPath, { locale: newLocale });
};
return (
<select
value={currentLocale}
onChange={(e) => handleLocaleChange(e.target.value)}
>
{locales?.map((loc) => (
<option key={loc} value={loc}>
{loc.toUpperCase()}
</option>
))}
</select>
);
}
사용자가 선택을 변경하면 쿠키가 설정되고 라우터는 새 로케일로 동일한 페이지로 이동합니다. 쿠키는 이후의 모든 요청에서 사용할 수 있습니다.
3. 루트 페이지에서 저장된 환경설정 확인하기
루트 페이지의 getServerSideProps에서 쿠키를 읽고 저장된 로케일이 존재하고 유효한 경우 해당 로케일로 리디렉션합니다.
import { GetServerSideProps } from "next";
export const getServerSideProps: GetServerSideProps = async (context) => {
const storedLocale = context.req.cookies.NEXT_LOCALE;
const { locales, defaultLocale } = context;
if (
storedLocale &&
locales?.includes(storedLocale) &&
storedLocale !== defaultLocale
) {
return {
redirect: {
destination: `/${storedLocale}`,
permanent: false,
},
};
}
return {
redirect: {
destination: `/${defaultLocale}`,
permanent: false,
},
};
};
export default function RootPage() {
return null;
}
이것은 NEXT_LOCALE 쿠키가 존재하고 애플리케이션의 구성된 목록에서 유효한 로케일을 포함하는지 확인합니다. 저장된 로케일이 기본값이 아닌 경우, 사용자는 해당 로케일의 루트로 리디렉션됩니다. 그렇지 않으면 기본 로케일로 리디렉션됩니다. 리디렉션은 렌더링 전에 서버 측에서 발생하여 사용자가 즉시 올바른 로케일에 도달하도록 보장합니다.
4. Next.js에서 로케일 라우팅 구성하기
next.config.js에서 지원되는 로케일을 정의하여 리디렉션 로직이 저장된 환경설정을 검증할 수 있도록 합니다.
module.exports = {
i18n: {
locales: ["en", "fr", "de", "es"],
defaultLocale: "en",
},
};
이 구성은 Next.js의 내장 i18n 라우팅을 활성화하고 getServerSideProps에서 locales와 defaultLocale을 사용할 수 있게 합니다. 루트 페이지 로직은 이 값들을 사용하여 저장된 쿠키를 검증하고 올바른 리디렉션 대상을 구성합니다.