TanStack Start v1에서 세션 간 언어 선택을 기억하는 방법
사용자의 명시적 언어 선택 저장
문제
사용자가 명시적으로 언어를 선택하면 해당 선택은 현재 브라우저 세션을 넘어 지속되어야 하는 의도적인 선호도를 나타냅니다. 지속성이 없으면 애플리케이션은 방문할 때마다 이 선호도를 잊어버려 사용자가 반복적으로 언어를 다시 선택해야 합니다. 이는 마찰을 일으키고 애플리케이션이 사용자 선택을 존중하지 않는다는 신호를 보내 전반적인 경험을 저하시키고 잠재적으로 사용자가 의도한 작업을 완료하기 전에 사이트를 떠나게 만들 수 있습니다.
솔루션
사용자가 명시적으로 선택할 때 사용자의 언어 선택을 지속 쿠키에 저장합니다. 후속 방문 시 브라우저 헤더와 같은 자동 감지 방법으로 대체하기 전에 이 저장된 선호도를 확인합니다. 유효한 저장된 언어가 발견되면 사용자를 사이트 루트에서 해당 언어의 경로로 리디렉션하여 추가 단계 없이 선호하는 로케일에 직접 도달하도록 합니다.
단계
1. 언어 선호도를 저장하는 서버 함수 생성
서버 함수를 사용하면 애플리케이션의 어디에서나 호출할 수 있는 서버 전용 로직을 정의할 수 있습니다. 선택한 로케일을 쿠키에 기록하는 함수를 정의합니다.
import { createServerFn } from "@tanstack/react-start";
import { setCookie } from "@tanstack/react-start/server";
const LOCALE_COOKIE = "user_locale";
const COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
export const saveLocalePreference = createServerFn({ method: "POST" })
.validator((locale: string) => locale)
.handler(async ({ data }) => {
setCookie(LOCALE_COOKIE, data, {
maxAge: COOKIE_MAX_AGE,
path: "/",
sameSite: "lax",
});
return { success: true };
});
이 서버 함수는 @tanstack/react-start/server의 setCookie를 사용하여 로케일 기본 설정을 저장하고, 향후 요청에서 사용할 수 있도록 합니다.
2. 사용자가 언어를 선택할 때 저장 함수 호출
언어 전환기 컴포넌트에서 사용자가 선택한 후 서버 함수를 호출합니다.
import { useNavigate } from "@tanstack/react-router";
import { saveLocalePreference } from "./locale-preference";
export function LanguageSwitcher({ currentLocale }: { currentLocale: string }) {
const navigate = useNavigate();
const handleLocaleChange = async (newLocale: string) => {
await saveLocalePreference({ data: newLocale });
navigate({ to: `/${newLocale}` });
};
return (
<select
value={currentLocale}
onChange={(e) => handleLocaleChange(e.target.value)}
>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
);
}
이렇게 하면 새 로케일로 이동하기 전에 선호도가 저장됩니다.
3. 저장된 선호도를 읽는 서버 함수 생성
쿠키에서 저장된 로케일을 가져오는 함수를 정의합니다.
import { createServerFn } from "@tanstack/react-start";
import { getCookie } from "@tanstack/react-start/server";
const LOCALE_COOKIE = "user_locale";
export const getStoredLocale = createServerFn({ method: "GET" }).handler(
async () => {
const stored = getCookie(LOCALE_COOKIE);
return stored || null;
},
);
@tanstack/react-start/server의 getCookie 함수는 이전 방문에서 설정된 쿠키 값을 읽습니다.
4. 루트 경로에서 저장된 기본 설정 확인
저장된 기본 설정이 발견되면 리디렉션을 트리거하기 위해 라우트의 beforeLoad 콜백에서 redirect 함수를 사용하세요.
import { createFileRoute, redirect } from "@tanstack/react-router";
import { getStoredLocale } from "./locale-preference";
const SUPPORTED_LOCALES = ["en", "es", "fr"];
const DEFAULT_LOCALE = "en";
export const Route = createFileRoute("/")({
beforeLoad: async () => {
const stored = await getStoredLocale();
if (stored && SUPPORTED_LOCALES.includes(stored)) {
throw redirect({ to: `/${stored}` });
}
throw redirect({ to: `/${DEFAULT_LOCALE}` });
},
});
저장된 기본 설정을 먼저 확인하고 유효한 경우 해당 로케일로 리디렉션하며, 그렇지 않으면 기본값으로 폴백합니다.
5. 지원되는 언어에 대해 저장된 로케일 유효성 검사
리디렉션하기 전에 저장된 값이 인식된 로케일인지 확인하기 위한 유효성 검사를 추가합니다.
import { createFileRoute, redirect } from "@tanstack/react-router";
import { getStoredLocale } from "./locale-preference";
const SUPPORTED_LOCALES = ["en", "es", "fr", "de", "ja"] as const;
function isValidLocale(value: string | null): value is string {
return value !== null && SUPPORTED_LOCALES.includes(value as any);
}
export const Route = createFileRoute("/")({
beforeLoad: async () => {
const stored = await getStoredLocale();
const locale = isValidLocale(stored) ? stored : "en";
throw redirect({ to: `/${locale}` });
},
});
유효하지 않거나 지원되지 않는 로케일로의 리디렉션을 방지하여 쿠키 변조나 오래된 값으로부터 보호합니다.