robots.txt와 sitemap.xml은 파일 크기로 보면 아주 작지만, 운영에서 은근히 자주 틀어지는 파일입니다. 사이트 전체는 멀쩡해 보여도 robots.txt가 preview 도메인을 가리키고 있거나, sitemap.xml이 상대 경로를 내보내고 있거나, 이미 noindex인 페이지를 sitemap에 계속 넣고 있으면 검색 엔진 쪽 기본기가 흐려집니다. 그리고 이런 문제는 페이지 UI만 봐서는 잘 안 보입니다.

이 레포도 이미 robots.tssitemap.ts로 기본 파일을 자동 생성하고 있습니다. 이전 글에서 Next.js에서 sitemap.xml과 robots.txt를 자동 생성하는 방법을 정리했지만, 자동 생성이 곧 자동 검증을 의미하지는 않습니다. 실제 운영에서는 “파일이 존재하느냐”보다 “의도한 규칙을 지금도 계속 만족하느냐”가 더 중요합니다. 그래서 작은 점검 도구가 따로 가치가 생깁니다.

Google Search Central 문서를 보면 이 도구가 왜 필요한지도 분명해집니다. robots.txt는 크롤러 접근을 관리하는 파일이지, 페이지를 검색 결과에서 숨기는 장치가 아니라고 Google은 명시합니다. sitemap 역시 “중요한 URL을 알려주는 파일”이지, 색인을 보장하는 파일은 아닙니다. 즉 둘 다 존재만 하면 끝나는 게 아니라, 목적에 맞게 정확하게 유지돼야 합니다.

그래서 저는 robots/sitemap 점검 도구를 만들 때, “표준을 다 검사하는 범용 validator”보다는 “작은 사이트 운영자가 반복적으로 다시 보게 되는 체크포인트”에 집중하는 편이 좋다고 생각합니다. 이 글은 그런 기준을 정리한 제작 메모입니다. 현재 이 레포처럼 정적 export로 배포하는 Next.js 블로그와 작은 도구 사이트를 함께 운영하는 구조를 기준으로 설명하겠습니다.

도구 제작점검 도구

robots.txt와 sitemap 점검 도구를 만들며 정리한 기준

robots.txt와 sitemap.xml은 작지만 자주 잘못 배포되는 파일입니다. 정적 블로그를 운영하며 어떤 항목을 자동으로 점검하면 좋은지, 그리고 왜 별도 점검 도구가 운영 효율을 높이는지 정리합니다.

핵심 1

먼저 결론: 이 도구는 “파일 유무 검사기”가 아니라 “검색 기본기 회귀 테스트”에 가깝다

핵심 2

왜 자동 생성만으로 충분하지 않은가

핵심 3

robots.txt에서 가장 먼저 볼 항목은 “차단 규칙”보다 “기대와 현실의 차이”다

점검 도구도구 제작robots sitemap audit tool
robots.txt와 sitemap.xml 점검 도구가 상태 코드, 허용 규칙, sitemap 위치, 절대 URL, lastmod, canonical 의도를 순서대로 검사하는 흐름

먼저 결론: 이 도구는 “파일 유무 검사기”가 아니라 “검색 기본기 회귀 테스트”에 가깝다

제가 robots/sitemap 점검 도구를 만들며 먼저 정한 원칙은 단순합니다.

  1. robots.txt와 sitemap.xml을 함께 본다
  2. 문법 전체보다 운영에서 자주 틀리는 포인트를 우선한다
  3. 경고는 “왜 문제인지”까지 같이 설명한다
  4. 사이트 구조 의도와 연결해 보여준다
  5. 실제 fetch 결과를 기준으로 판단한다

이 원칙이 중요한 이유는 robots와 sitemap이 서로 완전히 분리된 파일이 아니기 때문입니다. 예를 들어 robots.txt 안에 sitemap 주소가 없거나 잘못된 호스트를 가리키면, sitemap 파일 자체가 정상이어도 운영 품질은 떨어집니다. 반대로 sitemap에 넣은 URL이 robots에서 막혀 있거나, canonical 의도와 엇갈려도 문제가 됩니다.

즉 점검 도구는 “두 파일이 각각 유효한가”보다 “둘이 같은 방향을 가리키는가”를 같이 봐야 쓸모가 커집니다.

1. 왜 자동 생성만으로 충분하지 않은가

현재 레포의 기본 구현은 아주 깔끔합니다.

src/app/robots.ts

import type { MetadataRoute } from "next";
import { getSiteUrl } from "@/lib/site-url";

const siteUrl = getSiteUrl();

export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: "*",
      allow: "/",
    },
    sitemap: `${siteUrl}/sitemap.xml`,
  };
}

src/app/sitemap.ts

import type { MetadataRoute } from "next";
import { getPublishedArticles } from "@/lib/article-content";
import { getSiteUrl } from "@/lib/site-url";

const siteUrl = getSiteUrl();

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const staticRoutes = ["", "/blog", "/about", "/contact", "/privacy", "/terms"];
  const articles = await getPublishedArticles();

  const staticEntries = staticRoutes.map((route) => ({
    url: `${siteUrl}${route}`,
    lastModified: new Date(),
  }));

  const postEntries = articles.map((article) => ({
    url: `${siteUrl}/blog/${article.slug}`,
    lastModified: new Date(article.updatedAt ?? article.publishedAt),
  }));

  return [...staticEntries, ...postEntries];
}

이런 구조는 생성 관점에서는 충분히 좋습니다. 하지만 운영 관점에서는 여전히 여러 변수가 남습니다.

  • NEXT_PUBLIC_SITE_URL이 잘못 설정될 수 있습니다.
  • 배포 후 robots.txt가 200이 아니라 404를 내보낼 수 있습니다.
  • sitemap 안 URL이 canonical 의도와 달라질 수 있습니다.
  • 발행되지 않은 페이지가 나중에 잘못 포함될 수 있습니다.
  • 특정 페이지가 noindex가 됐는데 sitemap에는 계속 남을 수 있습니다.

즉 생성 로직이 맞아도, 결과물 검사는 별도 계층으로 두는 편이 좋습니다.

2. robots.txt에서 가장 먼저 볼 항목은 “차단 규칙”보다 “기대와 현실의 차이”다

Google의 robots.txt 소개 문서는 robots.txt가 검색 결과 차단 장치가 아니라고 분명히 설명합니다. Google은 이 파일이 주로 크롤링 트래픽을 관리하는 용도이며, 페이지를 검색 결과에서 완전히 숨기고 싶다면 noindex나 비밀번호 보호 같은 다른 방법을 써야 한다고 안내합니다.

이 사실을 점검 도구로 옮기면 중요한 체크포인트가 생깁니다.

  • 사용자가 robots에 page hide 기능을 기대하고 있지는 않은가
  • Disallow로 막은 URL을 sitemap에도 넣고 있지는 않은가
  • CSS/JS 리소스를 막아서 페이지 이해를 방해하고 있지는 않은가
  • sitemap 위치가 robots 안에 선언되어 있는가

즉 robots 점검 도구는 문법 체크보다 먼저 “이 규칙이 정말 원하는 효과를 내는가”를 경고하는 편이 훨씬 유용합니다.

예를 들면 이런 경고가 가치가 큽니다.

  • Disallow: /private/가 있지만 해당 경로가 여전히 외부 링크로 노출되면 URL 자체는 검색 결과에 보일 수 있습니다.
  • Disallow: /blog/ 같은 과한 규칙은 작은 블로그 전체를 사실상 막아버릴 수 있습니다.
  • Sitemap: 줄이 없으면 파일이 있어도 robots 기준 탐색 경로가 흐려질 수 있습니다.

3. robots 점검 도구에서 제가 기본으로 넣는 체크포인트

제가 우선 넣고 싶은 robots 점검 항목은 아래 정도입니다.

3-1. 상태 코드와 콘텐츠 존재 여부

  • /robots.txt가 200으로 열리는가
  • body가 비어 있지 않은가

3-2. 기본 규칙 검사

  • User-agent가 있는가
  • 최소한의 allow/disallow 규칙이 있는가
  • sitemap 지시문이 있는가

3-3. 위험 패턴 검사

  • 사이트 전체를 막는 Disallow: /가 있는가
  • CSS/JS 경로를 막고 있지는 않은가
  • admin, draft, preview 의도가 아닌데 넓은 범위를 막고 있지는 않은가

3-4. 설명형 경고

  • robots는 noindex 대체가 아니라는 점
  • disallowed URL도 외부 링크를 통해 검색 결과에 나타날 수 있다는 점

이 마지막 항목이 특히 중요합니다. 운영 도구는 검사 결과를 “틀림/맞음”으로만 보여주기보다, 왜 그 규칙이 위험한지 설명해야 다시 쓰게 됩니다.

4. sitemap은 “XML이 맞는가”보다 “대표 URL 목록이 맞는가”를 본다

Google의 sitemap 문서를 보면, sitemap은 사이트의 중요한 URL과 그 관계를 검색 엔진에 알려주는 파일입니다. 그리고 build 문서는 sitemap에 fully-qualified, absolute URL을 사용하라고 분명히 설명합니다. 또한 sitemap에는 검색 결과에 보여주고 싶은 canonical URL을 넣으라고도 안내합니다.

즉 sitemap 점검 도구의 핵심 질문은 아래와 같습니다.

  • 이 파일이 파싱 가능한가
  • absolute URL만 포함하는가
  • canonical로 밀고 싶은 URL만 포함하는가
  • lastmod가 신뢰 가능한가
  • robots나 noindex 의도와 충돌하지 않는가

Google은 또 XML sitemap에서 <priority><changefreq>를 무시한다고 설명합니다. 그래서 저는 이 항목을 굳이 과하게 강조하지 않고, 오히려 <loc><lastmod> 품질에 더 집중하는 편이 낫다고 봅니다.

5. sitemap 점검 도구에서 먼저 넣을 항목

제가 우선 넣고 싶은 sitemap 체크는 아래 정도입니다.

5-1. 접근 가능성과 기본 파싱

  • /sitemap.xml이 200으로 열리는가
  • XML 구조가 깨지지 않았는가
  • <urlset> 또는 sitemap index 구조가 있는가

5-2. URL 품질

  • 모든 <loc>가 absolute URL인가
  • 호스트가 대표 도메인과 일치하는가
  • 중복 URL이 없는가
  • query-heavy URL이나 preview URL이 섞여 있지 않은가

5-3. 운영 의도 검사

  • sitemap 안 URL이 canonical로 쓰고 싶은 URL과 같은가
  • robots로 막아둔 경로를 sitemap에 넣고 있지는 않은가
  • noindex 페이지가 있으면 sitemap에 남아 있는지 검토 경고
  • lastmod가 무의미하게 전부 같은 시각으로 바뀌고 있지는 않은가

5-4. 규모 관련 체크

Google 문서는 단일 sitemap이 50MB 비압축 또는 50,000 URL 제한을 가진다고 설명합니다. 작은 블로그에서는 거의 문제가 안 되지만, 도구는 이 한계도 같이 경고할 수 있습니다.

즉 이 도구의 목적은 “XML validator”가 아니라 “실제로 검색에 보여주고 싶은 URL 목록이 맞는지”를 확인하는 것입니다.

6. 이 도구는 robots와 sitemap을 따로 보여주되, 마지막엔 같이 묶어 보여줘야 한다

운영 경험상 robots와 sitemap을 분리해 읽는 화면은 필요합니다. 하지만 마지막 결과는 한곳에 묶여야 훨씬 실용적입니다. 예를 들어 이런 요약 패널이 있으면 좋습니다.

  • robots 상태: 정상 / 경고 / 위험
  • sitemap 상태: 정상 / 경고 / 위험
  • 대표 도메인 일치 여부
  • 차단된 URL과 sitemap URL 충돌 여부
  • 검색 기본기 총평

이렇게 하면 사용자는 “robots는 맞고 sitemap만 틀렸는지”, “둘 다 맞는데 도메인만 어긋났는지”를 한눈에 볼 수 있습니다.

저는 이걸 “검색 기본기 회귀 테스트”처럼 보는 편이 좋다고 생각합니다. 새 배포 뒤에 한 번 돌려보면, 아주 작은 설정 실수도 바로 잡히기 때문입니다.

7. URL 검사 도구는 정적 페이지보다 서버 경계가 더 적합하다

이 레포는 output: "export"를 쓰고 있어서, 외부 URL을 직접 검사하는 기능은 정적 페이지 안에만 두기 어렵습니다. 브라우저에서 바로 다른 사이트의 /robots.txt/sitemap.xml을 읽으려 하면 CORS 때문에 막히는 경우가 많고, 응답 상태 코드나 redirect 최종 URL을 안정적으로 다루기도 번거롭습니다.

그래서 이 도구도 이전 문의 폼이나 메타태그 미리보기 URL 검사 모드와 비슷하게, 서버 경계를 하나 두는 편이 좋습니다.

  • 정적 UI: /tools/search-basics-checker
  • 검사 API: Cloudflare Pages Function

이렇게 두면 UI는 여전히 가볍고, fetch와 파싱은 서버 쪽에서 맡게 됩니다.

8. robots와 sitemap은 텍스트 기반이라 작은 파서로도 충분하다

메타태그 검사처럼 HTML 전체를 파싱해야 하는 경우와 달리, robots와 sitemap은 비교적 단순합니다. robots.txt는 거의 line-based parsing으로도 충분하고, sitemap도 작은 XML 파서나 제한된 정규화 단계로 핵심 검사 항목을 뽑아낼 수 있습니다.

예를 들면 robots는 이렇게 접근할 수 있습니다.

type RobotsAudit = {
  status: number;
  sitemap: string | null;
  disallowsRoot: boolean;
  warnings: string[];
};

function auditRobots(text: string, status: number): RobotsAudit {
  const lines = text.split(/\r?\n/).map((line) => line.trim());
  const sitemapLine = lines.find((line) => line.toLowerCase().startsWith("sitemap:"));
  const disallowsRoot = lines.some((line) => /^disallow:\s*\/$/i.test(line));

  const warnings: string[] = [];

  if (!sitemapLine) warnings.push("robots.txt에 Sitemap 지시문이 없습니다.");
  if (disallowsRoot) warnings.push("사이트 전체를 차단하는 Disallow: / 규칙이 있습니다.");

  return {
    status,
    sitemap: sitemapLine ? sitemapLine.split(":").slice(1).join(":").trim() : null,
    disallowsRoot,
    warnings,
  };
}

그리고 sitemap 쪽은 핵심 loc만 먼저 읽어도 초기 버전에 충분합니다.

type SitemapAudit = {
  status: number;
  urls: string[];
  warnings: string[];
};

function extractLocs(xml: string) {
  return [...xml.matchAll(/<loc>(.*?)<\/loc>/g)].map((match) => match[1].trim());
}

이건 완전한 XML 파서가 아니지만, 운영용 v1 도구에서는 “absolute URL인가”, “대표 호스트와 맞는가”, “sitemap이 비어 있지는 않은가” 같은 체크를 빠르게 만들 수 있습니다.

9. 제가 먼저 넣고 싶은 경고 문구들

이 도구는 단순한 pass/fail보다, 운영자가 바로 이해할 수 있는 경고 문구가 중요합니다. 예를 들면 아래 같은 메시지가 좋습니다.

  • robots.txt는 페이지를 검색 결과에서 숨기는 장치가 아닙니다. 차단이 아니라 noindex가 필요할 수 있습니다.
  • sitemap에는 relative URL이 아니라 absolute URL을 넣는 편이 좋습니다.
  • sitemap에 포함된 URL 중 일부가 preview 또는 임시 도메인을 사용합니다.
  • lastmod가 모든 페이지에서 동일하게 갱신되고 있어 신뢰도가 낮을 수 있습니다.
  • robots.txt의 sitemap 경로와 실제 sitemap URL이 다릅니다.
  • sitemap에 포함된 일부 URL은 robots 규칙과 충돌할 수 있습니다.

이런 문구가 있어야 도구가 단순한 개발자 장난감이 아니라, 실제 운영자용 체크리스트가 됩니다.

10. 이 도구를 왜 블로그와 함께 운영할 가치가 있는가

이런 도구는 “검색 트릭”을 주는 도구가 아닙니다. 오히려 사이트 기본기를 확인하게 해 주는 도구입니다. 그래서 블로그와 함께 있을 때 더 가치가 큽니다.

  • 글에서는 원리와 정책을 설명합니다.
  • 도구에서는 실제 사이트를 넣어 점검합니다.
  • 둘이 함께 있으면 글의 신뢰도도 올라갑니다.

특히 이 사이트처럼 검색, 구조, 성능, 운영을 다루는 기술 출판물에서는, robots/sitemap 점검 도구가 콘텐츠와 도구 사이의 연결점 역할을 잘 합니다. 메타 미리보기 도구가 메타데이터 글과 연결되듯, 이 도구는 크롤링과 색인 기본기 글들과 자연스럽게 연결됩니다.

실무 체크리스트

  • /robots.txt/sitemap.xml을 함께 점검하는가
  • robots는 “페이지 숨김” 도구가 아니라는 경고를 제공하는가
  • sitemap 안 URL이 absolute URL인지 검사하는가
  • sitemap URL 호스트가 대표 도메인과 일치하는지 보는가
  • robots 안의 sitemap 지시문과 실제 sitemap 경로를 함께 비교하는가
  • sitemap에 canonical 의도와 맞는 URL만 들어 있는지 점검하는가
  • <priority><changefreq>보다 <loc><lastmod> 품질을 더 우선하는가
  • 정적 export 환경에 맞게 서버 경계에서 검사하도록 설계했는가

마무리

robots.txt와 sitemap.xml은 파일 자체가 작아서, 오히려 “대충 맞겠지” 하고 넘어가기 쉬운 영역입니다. 하지만 검색 엔진 입장에서는 사이트 기본기를 보여주는 파일이기도 합니다. 그래서 자동 생성만 해두고 끝내기보다, 배포 후 결과물을 빠르게 재점검하는 도구가 따로 있으면 훨씬 안정적입니다.

이 도구의 핵심은 복잡한 표준 구현보다, 운영에서 자주 틀리는 포인트를 먼저 잡아주는 것입니다. robots는 noindex 대체가 아니고, sitemap은 absolute canonical 의도를 담아야 하며, 둘은 서로 같은 방향을 가리켜야 한다는 점만 꾸준히 체크해도 검색 기본기의 흔들림을 많이 줄일 수 있습니다.

참고 자료: