React Router v7에서 세션 간 언어 선택을 기억하는 방법
사용자의 명시적 언어 선택 저장
문제
사용자가 명시적으로 언어를 선택하면 해당 선택은 사용자의 선호도를 반영하며 자동 감지보다 우선해야 합니다. 지속성이 없으면 브라우저를 닫거나 세션이 종료될 때 이 선택이 사라집니다. 다음 방문 시 애플리케이션이 새로 시작되어 사용자가 다시 언어를 선택해야 합니다. 이러한 반복은 애플리케이션이 사용자의 선호도를 존중하지 않는다는 신호를 보내며 마찰을 일으키고 신뢰를 떨어뜨립니다.
솔루션
사용자가 선택할 때 쿠키와 같은 영구 저장소에 사용자의 언어 선택을 저장합니다. 후속 방문 시 브라우저 헤더나 다른 감지 방법으로 대체하기 전에 저장된 선호도를 확인합니다. 유효한 저장된 언어가 발견되면 사용자를 해당 언어의 경로로 자동으로 리디렉션합니다. 이를 통해 명시적 선택이 우선순위를 갖고 세션 간에 지속되도록 보장합니다.
단계
1. 언어 선호도 저장을 위한 쿠키 생성
긴 만료 시간으로 사용자가 선택한 언어를 보유할 쿠키를 정의합니다.
import { createCookie } from "react-router";
export const languagePreference = createCookie("language-preference", {
maxAge: 31536000,
httpOnly: false,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
});
이 쿠키는 1년 동안 지속되며 선호도를 읽기 위해 클라이언트 측 코드에서 액세스할 수 있습니다.
2. 언어 선택을 저장하는 액션 추가
언어 선택 폼 제출을 처리하고 선택을 쿠키에 저장하는 액션을 생성합니다.
import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";
export async function action({ request }: Route.ActionArgs) {
const formData = await request.formData();
const selectedLanguage = formData.get("language");
if (typeof selectedLanguage === "string") {
return redirect(`/${selectedLanguage}`, {
headers: {
"Set-Cookie": await languagePreference.serialize(selectedLanguage),
},
});
}
return redirect("/");
}
사용자가 언어 선택을 제출하면 이 액션은 쿠키에 저장하고 적절한 언어 경로로 리디렉션합니다.
3. 언어 선택 컴포넌트 생성
사용자가 선호하는 언어를 선택할 수 있는 폼 컴포넌트를 구축합니다.
import { Form } from "react-router";
export function LanguageSelector({
currentLanguage,
}: {
currentLanguage: string;
}) {
return (
<Form method="post">
<select
name="language"
defaultValue={currentLanguage}
onChange={(e) => e.currentTarget.form?.requestSubmit()}
>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
</select>
</Form>
);
}
이 컴포넌트는 사용자가 선택을 변경하면 자동으로 제출되어 환경설정을 저장하는 액션을 트리거합니다.
4. 루트 로더에서 저장된 환경설정 확인
저장된 언어 환경설정을 확인하고 그에 따라 리디렉션하는 로직을 루트 라우트 로더에 추가합니다.
import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const cookieHeader = request.headers.get("Cookie");
const storedLanguage = await languagePreference.parse(cookieHeader);
if (url.pathname === "/" && storedLanguage) {
return redirect(`/${storedLanguage}`);
}
return null;
}
사용자가 루트 경로를 방문하면 이 로더는 저장된 언어 환경설정을 확인하고 선택한 언어 라우트가 있는 경우 해당 라우트로 리디렉션합니다.
5. 지원되는 로케일에 대해 저장된 언어 유효성 검사
리디렉션에 사용하기 전에 저장된 환경설정이 유효한지 확인합니다.
import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";
const SUPPORTED_LANGUAGES = ["en", "es", "fr", "de"];
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
const cookieHeader = request.headers.get("Cookie");
const storedLanguage = await languagePreference.parse(cookieHeader);
if (
url.pathname === "/" &&
storedLanguage &&
SUPPORTED_LANGUAGES.includes(storedLanguage)
) {
return redirect(`/${storedLanguage}`);
}
return null;
}
이 유효성 검사는 쿠키 값이 변조되었거나 환경설정이 저장된 이후 지원 언어가 변경된 경우 유효하지 않거나 지원되지 않는 언어 라우트로 리디렉션되는 것을 방지합니다.