robots.txt 및 sitemap.xml 설정
robots.ts로 크롤링 허용 범위를 정하고 sitemap.ts로 색인할 URL과 갱신 정보를 검색 엔진에 제공합니다.
SEO를 최적화할 때 robots.txt와 sitemap.xml은 검색 엔진 크롤러에 주는 핵심 지침입니다.
이 두 파일은 웹사이트 노출성뿐 아니라, 검색 엔진이 사이트 구조를 효율적으로 이해하고 색인하는 데 큰 영향을 줍니다.
Next.js는 이 파일을 효과적으로 관리할 수 있는 방법을 제공해 SEO 친화적인 애플리케이션 구축을 돕습니다.
이 절에서는 robots.txt와 sitemap.xml의 역할과 중요성, Next.js App Router에서 이 파일들을 설정하는 방법, 그리고 SEO를 위한 최적화 전략에 대해 상세히 알아보겠습니다.
먼저 robots.txt와 sitemap.xml이 검색 엔진에 주는 신호가 어떻게 다른지 정리합니다.
두 파일은 대체 관계가 아니다. 크롤링 조절과 URL 발견은 색인 제외·보안과도 구분한다.
- robots.txt
크롤러가 방문할 경로의 범위를 조절한다.
- sitemap.xml
발견해야 할 공개 canonical URL을 알려준다.
- noindex
검색 결과에서 제외하려는 문서에 사용한다.
- 인증·인가
민감한 URL과 데이터의 접근을 실제로 막는다.
robots.txt
robots.txt 파일은 웹사이트의 루트 디렉토리에 위치하는 텍스트 파일입니다.
이 파일은 검색 엔진 크롤러(웹 로봇)에게 웹사이트 내에서 어떤 URL에 접근할 수 있고 없는지를 알려주는 역할을 합니다.
이는 검색 엔진이 어떤 URL을 크롤링할지 범위를 조절하고, 불필요한 요청으로 인한 서버 부하를 줄이는 데 사용됩니다.
주요 목적- 크롤링 범위 조절: 검색 엔진에 특정 디렉토리나 파일을 크롤링하지 말라고 요청합니다.
- 서버 부하 감소: 불필요한 페이지에 대한 크롤링 요청을 줄여 서버 리소스 낭비를 방지합니다.
- 크롤링 우선순위 정리: 중복·필터 URL보다 대표 콘텐츠를 먼저 탐색하도록 범위를 정리합니다.
주의사항: robots.txt는 보안 메커니즘이 아닙니다.
이 파일은 단순히 크롤러에게 "이곳은 가지 말아달라"고 요청하는 것이며, 악의적인 봇이나 직접 URL을 입력하는 사용자를 막을 수는 없습니다.
민감한 정보는 서버 측 인증이나 다른 보안 조치로 보호해야 합니다.
robots.txt 파일 구조
robots.txt는 User-agent와 Disallow, Allow, Sitemap 지시어로 구성됩니다.
User-agent: 특정 검색 엔진 봇을 지정합니다.*는 모든 봇을 의미합니다.- 예시:
User-agent: *(모든 봇),User-agent: Googlebot(구글 봇),User-agent: bingbot(빙 봇)
- 예시:
Disallow: 지정된 봇에 크롤링하지 말라고 요청할 경로를 지정합니다.- 예시:
Disallow: /admin/(admin 디렉토리 전체),Disallow: /private-page.html(특정 파일)
- 예시:
Allow:Disallow규칙 내에서 특정 서브 경로를 허용할 때 사용합니다.- 예시:
Disallow: /private/Allow: /private/public-page.html
- 예시:
Sitemap: 사이트맵 파일의 위치를 지정합니다. 이 지시어는 크롤러가 사이트맵을 쉽게 찾을 수 있도록 돕습니다.
App Router에서 robots.txt 설정
App Router에서는 정적 src/app/robots.txt와 동적으로 생성하는 src/app/robots.ts 중 하나를 선택합니다.
두 파일은 모두 /robots.txt를 만들기 때문에 한 프로젝트에서 함께 사용하지 않습니다.
이 교재에서는 환경이나 배포 주소에 따라 규칙을 확장하기 쉬운 src/app/robots.ts 한 가지 방식으로 통일합니다.
import type { MetadataRoute } from 'next';
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{
userAgent: '*', // 모든 봇
allow: '/', // 모든 페이지 허용
disallow: ['/admin/', '/private/'], // 특정 경로 비허용
},
{
userAgent: 'Googlebot', // Googlebot만
allow: '/',
disallow: ['/admin/', '/private/', '/temp/'],
},
],
sitemap: 'https://docs-lab.dev/sitemap.xml', // 사이트맵 경로
};
}구체적인 Googlebot 그룹은 * 그룹의 규칙을 자동 상속하지 않습니다.
두 그룹 모두 막아야 하는 경로는 각 그룹에 명시합니다.
Next.js는 이 반환값을 robots.txt 형식으로 변환해 사이트의 루트 경로인 https://docs-lab.dev/robots.txt에서 제공합니다.
sitemap.xml: 검색 엔진을 위한 웹사이트 지도
sitemap.xml 파일은 웹사이트의 중요한 페이지 목록을 검색 엔진에 제공하는 XML 파일입니다.
이 파일은 검색 엔진이 웹사이트의 콘텐츠를 효율적으로 발견하고 크롤링하며 색인하도록 돕습니다.
특히 내부 링크가 적거나 깊이 숨겨진 페이지, 동적으로 생성되는 페이지처럼 검색 엔진이 자체적으로 발견하기 어려운 페이지를 노출하는 데 매우 중요합니다.
주요 목적- 크롤링 효율성 증대: 검색 엔진이 웹사이트의 모든 중요한 URL을 빠르고 효율적으로 찾을 수 있도록 합니다.
- 누락 방지: 내부 링크 구조가 복잡하거나 새로운 페이지가 추가되었을 때, 검색 엔진이 해당 페이지를 놓치지 않도록 보장합니다.
- 추가 정보 제공: 각 URL에 대한 최종 수정일, 변경 빈도, 상대적 우선순위 등 검색 엔진에게 유용한 추가 정보를 제공할 수 있습니다.
sitemap.xml 파일 구조
sitemap.xml은 <urlset> 루트 요소 아래에 각 URL에 대한 <url> 요소를 포함합니다.
각 <url> 요소는 다음을 포함할 수 있습니다.
<loc>: (필수) 페이지의 전체 URL (절대 경로).<lastmod>: (선택) 페이지가 최종 수정된 날짜.<changefreq>: (선택) 페이지의 내용이 변경되는 빈도 (always, hourly, daily, weekly, monthly, yearly, never).<priority>: (선택) 웹사이트 내에서 이 URL의 상대적 중요도 (0.0 ~ 1.0). 기본값은 0.5.
App Router에서 sitemap.xml 설정
Next.js App Router는 src/app/sitemap.ts 또는 .js 파일을 통해 sitemap.xml을 생성할 수 있도록 지원합니다.
src/app/sitemap.ts를 사용한 사이트맵 생성
import { MetadataRoute } from 'next';
// 가상의 블로그 게시물 데이터
interface Post {
slug: string;
updatedAt: string;
}
async function getPosts(): Promise<Post[]> {
// 실제로는 여기서 DB 또는 API를 호출하여 모든 게시물의 slug와 업데이트 날짜를 가져옵니다.
// 예시를 위해 더미 데이터를 반환합니다.
return [
{ slug: 'nextjs-seo-guide', updatedAt: '2024-06-20T10:00:00Z' },
{ slug: 'dynamic-metadata-tutorial', updatedAt: '2024-06-21T15:30:00Z' },
{ slug: 'image-optimization-tips', updatedAt: '2024-06-19T09:00:00Z' },
];
}
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = 'https://docs-lab.dev'; // 실제 웹사이트 URL로 변경
// 1. 정적인 페이지 목록
const staticRoutes: MetadataRoute.Sitemap = [
{
url: baseUrl,
changeFrequency: 'daily', // 매일 변경될 가능성
priority: 1, // 가장 높은 우선순위
},
{
url: `${baseUrl}/about`,
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${baseUrl}/contact`,
changeFrequency: 'yearly',
priority: 0.7,
},
{
url: `${baseUrl}/blog`, // 블로그 목록 페이지
changeFrequency: 'weekly',
priority: 0.9,
}
];
// 2. 동적 블로그 게시물 목록
const posts = await getPosts();
const postRoutes: MetadataRoute.Sitemap = posts.map((post) => ({
url: `${baseUrl}/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly', // 블로그 게시물은 보통 weekly 또는 monthly
priority: 0.6,
}));
// 3. 모든 URL 목록을 반환
return [...staticRoutes, ...postRoutes];
}실제 수정 시각을 모르는 정적 페이지는 lastModified를 생략합니다.
매번 new Date()를 반환하면 변경되지 않은 페이지까지 방금 수정된 것처럼 보이므로, CMS나 소스 데이터에 저장된 수정 시각이 있을 때만 제공합니다.
이 파일을 생성하면 Next.js가 /sitemap.xml 경로에 사이트맵을 제공합니다.
SEO를 위한 최적화 전략
Next.js에서는 정적 파일과 App Router의 MetadataRoute 파일을 상황에 맞게 선택합니다.
사이트 전체 기본값과 route별 변형을 파일 위치로 분리한다.
- globallayout.tsx metadata
title template·기본 description·metadataBase
- crawlerrobots.ts
수집 허용 경로와 sitemap 위치
- discoverysitemap.ts
공개 canonical URL과 수정 시점 목록
- routegenerateMetadata
상품·글 데이터로 상세 title과 OG 생성
robots.txt와sitemap.xml은 함께 사용:robots.txt는Disallow규칙을 통해 크롤링을 제어하고,sitemap.xml은 크롤링을 원하는 모든 페이지를 명시하여 검색 엔진이 놓치는 페이지가 없도록 돕습니다. 두 파일은 상호 보완적입니다.robots.txt의Sitemap지시어 포함:robots.txt파일 내에Sitemap:지시어를 사용하여 사이트맵 파일의 전체 URL을 명시하는 것이 중요합니다. 이는 검색 엔진이 사이트맵을 쉽게 발견하도록 돕습니다.- Google Search Console에 등록: 사이트 속성을 확인하고
sitemap.xml을 제출합니다.robots.txt는 크롤러가 루트 경로에서 직접 읽으므로 실제 응답과 URL 검사 결과를 함께 확인합니다. - 크롤링과 인덱싱 구분:
robots.txt의Disallow는 크롤링을 제한할 뿐 검색 결과 제외를 보장하지 않습니다. 공개 페이지를 검색에서 제외하려면 크롤러가 읽을 수 있는noindex를 사용하고, 관리자 페이지와 개인정보는 인증·인가로 보호합니다. - 정확한
lastmod유지: 중요한 본문이 실제로 바뀐 시각만lastmod에 기록합니다.changefreq와priority는 Sitemap 프로토콜의 선택 필드지만 Google은 두 값을 무시하므로 크롤링 순위 조정 수단으로 사용하지 않습니다. - 동적 콘텐츠 관리: 블로그나 상품 URL은
sitemap.ts에서 저장소를 조회해 canonical URL을 열거합니다. 같은 목록을 빌드 시 미리 렌더링할 때만generateStaticParams와 데이터 조회 로직을 공유합니다. robots.txt변경 시 주의: 잘못된 규칙은 중요한 페이지의 크롤링을 막을 수 있습니다. 변경 후에는 실제 파일과 Search Console 보고서·URL 검사를 함께 확인합니다.- 파일 크기 제한:
sitemap.xml파일은 최대 50,000개의 URL 또는 50MB 크기로 제한됩니다. 이보다 큰 웹사이트의 경우 여러 개의 사이트맵 파일로 분할하고,sitemap index file을 사용하여 관리해야 합니다.
다음 다이어그램은 배포 전 robots.txt와 sitemap.xml을 함께 점검하는 흐름입니다.
잘못된 규칙은 중요 URL의 크롤링을 막지만 색인 제외를 보장하지 않는다.
- 생성·접근
루트 URL에서 두 파일이 200으로 응답하는지 확인한다.
- 정책 충돌
sitemap URL이 robots 규칙에 막히지 않는지 확인한다.
- 색인·보안
검색 제외는 noindex로, 민감 URL 보호는 인증·인가로 처리한다.
다음 다이어그램은 sitemap에 포함할 URL과 robots에서 차단할 URL을 서로 충돌하지 않게 나누는 기준입니다.
같은 URL에 “찾아 달라”와 “오지 말라”를 동시에 보내면 신호가 충돌한다.
- 공개 canonical
sitemap에 포함하고 robots에서 크롤링을 허용한다.
- 검색 제외
검색 결과에서 빼려면 noindex를 사용한다.
- 민감 URL
관리자·마이페이지는 인증과 인가로 보호한다.
- 중복·필터 URL
canonical과 크롤링 정책을 함께 설계한다.
다음 다이어그램은 운영 중 robots.txt와 sitemap.xml을 변경할 때 확인할 신호를 정리한 것입니다.
배포 후 즉시 반영되지 않으므로 의도와 검색 엔진 해석을 따로 확인한다.
- robots 변경허용·차단 범위를 바꾼 뒤 예상 URL만 접근되는지 확인한다
확인 · Allow/Disallow 해석 일치 · 위험 · 전체 사이트 차단
- sitemap 변경URL 추가·삭제 후 제출 상태와 발견 수를 확인한다
확인 · 읽은 URL 수 정상 · 위험 · 404·redirect 포함
- 검색 결과색인 제외가 의도인지 실수인지 구분한다.
확인 · 중요 URL 색인 가능 · 위험 · 제출했지만 차단
아래 다이어그램은 robots.txt와 sitemap.xml을 배포 전후에 함께 점검해 크롤링 허용 범위와 색인 대상이 충돌하지 않게 관리하는 기준입니다.
robots와 sitemap의 메시지가 엇갈리면 검색 엔진이 URL을 안정적으로 발견하지 못한다.
- 1핵심 1
배포 전후 SEO 파일 점검 기준 허용 범위와 색인 대상이 같은 방향인지 본다
- 2핵심 2
robots와 sitemap의 메시지가 엇갈리면 검색 엔진이 URL을 안정적으로 발견하지 못한다.
- 3핵심 3
시점 robots sitemap 실패 신호 배포 전 내부 URL 차단 공개 URL만 포함 차단 URL 포함 배포 직후 /robots.…
아래 다이어그램은 robots.txt의 접근 규칙과 sitemap.xml의 URL 목록이 SEO 흐름에서 맡는 역할을 비교합니다.
robots.txt와 sitemap.xml은 웹사이트의 기술적 SEO 기반을 다지는 데 매우 중요한 요소입니다.
Next.js App Router의 내장 기능을 활용하면 이 두 파일을 효율적으로 관리하여 검색 엔진 가시성을 극대화하고 더 나은 검색 결과를 얻을 수 있습니다.
아래 다이어그램은 robots.txt 및 sitemap.xml 설정을 크롤링 허용, 색인 대상, 갱신 신호 기준으로 점검합니다.
sitemap에 제출한 공개 URL은 크롤링 가능해야 하며, 색인 제외·보안 정책과도 충돌하지 않아야 한다.
- 크롤링
중요 공개 URL이 Allow/Disallow 규칙에 막히지 않는다.
- URL 발견
sitemap에는 200 응답의 공개 canonical URL만 넣는다.
- 색인 제외
검색 결과에서 뺄 문서는 noindex 정책을 확인한다.
- 보안
민감한 경로는 robots가 아니라 인증·인가로 보호한다.