React Router v7에서 다국어 사이트맵 만드는 방법
확장성을 위한 언어별 사이트맵 구성
문제
사이트맵은 검색 엔진이 사이트의 모든 페이지를 발견하고 크롤링하는 데 도움을 줍니다. 언어별로 수백 또는 수천 개의 페이지가 있는 다국어 사이트는 빠르게 거대한 사이트맵을 생성할 수 있습니다. 모든 언어에 대한 모든 URL을 나열하는 단일 파일은 다루기 어렵고, 50,000개 URL 또는 50MB 크기 제한을 초과할 수 있으며, 유지 관리를 어렵게 만듭니다. 한 언어의 구조를 업데이트할 때 전체 파일을 재생성하고 재검증해야 합니다. 이 접근 방식은 사이트가 성장함에 따라 확장되지 않습니다.
해결책
사이트맵을 계층 구조로 분할하여 별도의 언어별 사이트맵을 가리키는 최상위 사이트맵 인덱스를 만듭니다. 각 언어는 해당 언어의 URL만 포함하는 자체 사이트맵 파일을 갖습니다. 인덱스 파일은 디렉토리 역할을 하며 각 언어 사이트맵의 위치를 나열합니다. 이렇게 하면 개별 파일을 관리하기 쉽고, 각 언어를 독립적으로 업데이트할 수 있으며, 새로운 언어나 페이지를 추가할 때 잘 확장됩니다. 검색 엔진은 먼저 인덱스를 크롤링한 다음 각 언어 사이트맵으로 연결되는 링크를 따릅니다.
단계
1. 사이트맵 인덱스 라우트 생성
모든 언어별 사이트맵을 나열하는 XML 응답을 반환하는 리소스 라우트를 생성합니다.
import type { Route } from "./+types/sitemap";
const LOCALES = ["en", "es", "fr", "de"];
export function loader({ request }: Route.LoaderArgs) {
const { origin } = new URL(request.url);
const sitemapIndex = `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${LOCALES.map(locale => ` <sitemap>
<loc>${origin}/sitemap-${locale}.xml</loc>
</sitemap>`).join("
")}
</sitemapindex>`;
return new Response(sitemapIndex, {
headers: {
"Content-Type": "application/xml",
},
});
}
이 라우트는 XML 응답을 반환하여 API 엔드포인트로 작동합니다. 인덱스는 언어별로 하나의 사이트맵을 나열하므로 LOCALES 배열을 업데이트하여 언어를 쉽게 추가하거나 제거할 수 있습니다.
2. 언어별 사이트맵 경로 생성하기
각 언어별 개별 사이트맵을 생성하기 위해 동적 세그먼트가 있는 리소스 경로를 정의합니다.
import type { Route } from "./+types/sitemap.$locale";
export async function loader({ params }: Route.LoaderArgs) {
const locale = params.locale;
const urls = await getUrlsForLocale(locale);
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls.map(url => ` <url>
<loc>${url}</loc>
</url>`).join("
")}
</urlset>`;
return new Response(sitemap, {
headers: {
"Content-Type": "application/xml",
},
});
}
async function getUrlsForLocale(locale: string): Promise<string[]> {
return [];
}
경로 경로의 동적 세그먼트는 파싱되어 params.locale로 제공됩니다. 각 언어 사이트맵에는 해당 로케일에 대한 URL만 포함됩니다.
3. 각 언어별 페이지 가져오기
데이터 소스에서 주어진 로케일에 대한 모든 페이지를 검색하는 헬퍼 함수를 구현합니다.
async function getUrlsForLocale(locale: string): Promise<string[]> {
const pages = await db.pages.findMany({
where: { locale, published: true },
select: { slug: true },
});
return pages.map((page) => `https://example.com/${locale}/${page.slug}`);
}
이 함수는 요청된 언어로 발행된 페이지를 데이터베이스나 콘텐츠 소스에서 쿼리하고 전체 URL을 구성합니다. 쿼리와 URL 구조를 애플리케이션에 맞게 조정하세요.
4. 사이트맵 경로 등록하기
사이트맵 경로를 경로 구성 파일에 추가합니다.
import { type RouteConfig, route } from "@react-router/dev/routes";
export default [
route("sitemap.xml", "./routes/sitemap.tsx"),
route("sitemap-:locale.xml", "./routes/sitemap.$locale.tsx"),
] satisfies RouteConfig;
각 경로에는 일치시킬 URL 패턴과 경로 모듈의 파일 경로가 있습니다. 인덱스 경로는 /sitemap.xml에서 응답하고 언어 경로는 /sitemap-en.xml, /sitemap-es.xml 등에서 응답합니다.
5. robots.txt에 사이트맵 인덱스 추가하기
공개 디렉토리의 루트에 있는 robots.txt 파일에서 검색 엔진이 사이트맵 인덱스를 찾을 수 있도록 안내합니다.
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml
각 사이트맵을 나열하는 사이트맵 인덱스를 사용하면 검색 엔진이 단일 진입점에서 모든 언어별 사이트맵을 발견할 수 있습니다. 검색 엔진은 인덱스를 크롤링하고 각 언어 사이트맵으로 연결되는 링크를 자동으로 따라갑니다.