AI 에이전트용 마크다운: Accept text/markdown, Content-Signal, Link 헤더 정리
핵심 답변: AI 에이전트용 마크다운이란, 클라이언트가 요청 헤더
Accept: text/markdown으로 요청할 때 서버가 같은 주소에서 HTML 대신 일반 마크다운으로 응답하게 하는 것입니다. 브라우저는 계속 HTML을 받습니다. 서버 코드 몇 줄이나 켜기만 하면 되는 CDN 기능으로 구현할 수 있고, 에이전트는 메뉴와 스크립트가 없는 깔끔한 텍스트를 받습니다. 순위나 AI 인용에 도움이 된다는 증거는 없으므로, 읽을 수 있는 HTML, 잘 짜인 robots.txt, 사이트맵 위에 얹는 저렴한 추가 기능으로 보세요. 이것들을 대신해서는 안 됩니다.
AI 에이전트는 왜 마크다운을 좋아할까요?
웹 페이지는 브라우저를 위해 만들어졌습니다. 읽으려는 텍스트 주변에는 내비게이션, 쿠키 배너, 스크립트, 스타일 클래스, 푸터가 있습니다. 사람의 눈은 이 모두를 건너뜁니다. 페이지를 언어 모델에 넘겨야 하는 프로그램은 공짜로 건너뛸 수 없습니다. 모델의 컨텍스트 윈도우는 제한되어 있고, 요소가 하나 늘 때마다 그 일부를 차지하기 때문입니다.
마크다운은 읽는 데 중요한 것, 곧 제목, 문단, 목록, 표, 링크만 남깁니다. 그래서 에이전트 같은 도구가 마크다운을 요청하는 것은 자연스러운 일이고, llms.txt 제안도 마크다운으로 쓰여 있습니다. 이 파일은 llms.txt란? 만드는 방법과 실제로 효과가 있는지 정리에서 다뤘습니다.
Cloudflare는 크기 차이를 눈에 보이게 합니다. Markdown for Agents 발표문의 예시 응답에는 추정 토큰 수를 담은 x-markdown-tokens 헤더가 들어 있습니다(예시에서는 725). 클라이언트는 이 값으로 페이지가 컨텍스트를 얼마나 차지할지 가늠할 수 있습니다.
다만 이것만으로는 대형 AI 검색 시스템이 마크다운을 요청하는지 알 수 없습니다. Cloudflare 발표문에는 OAI-SearchBot에 대한 마크다운 응답을 보여 주는 Radar 데이터가 있습니다. 이는 그런 응답이 존재한다는 증거일 뿐 크롤러가 이를 요청한다는 증거는 아니며, OpenAI도 이를 문서화하지 않았습니다. 그래서 우리는 그렇다고 주장하지 않습니다. 문서로 확인되는 것은 일부 에이전트가 이미 요청한다는 점이며, 다음 섹션에서 설명합니다.
콘텐츠 협상의 원리: Accept, Vary, Content-Type
콘텐츠 협상(content negotiation)은 HTTP의 오래된 기능입니다. 한 주소가 여러 표현을 가질 수 있고, 클라이언트가 선호하는 것을 알립니다. 세 가지 헤더가 전체 메커니즘을 이룹니다.
| 헤더 | 보내는 쪽 | 의미 |
|---|---|---|
Accept | 클라이언트(요청) | 원하는 콘텐츠 유형. 가중치(q=0.8)를 붙일 수 있음 |
Content-Type | 서버(응답) | 서버가 실제로 보낸 유형. 여기서는 text/markdown; charset=utf-8 |
Vary: Accept | 서버(응답) | 응답이 Accept 헤더에 따라 달라지므로 캐시가 두 버전을 섞으면 안 됨 |
브라우저는 text/html을 먼저 적고 대체용으로 와일드카드 */*를 덧붙입니다. 마크다운을 원하는 에이전트는 Accept: text/markdown이나 Accept: text/markdown, text/html;q=0.8처럼 명시적으로 적습니다. Cloudflare는 Claude Code와 OpenCode 같은 대표적인 코딩 에이전트가 이런 Accept 헤더를 이미 보낸다고 밝혔습니다.
모두를 안전하게 지키는 규칙은 간단합니다. text/markdown이 명시적으로 적혀 있고 text/html보다 낮게 평가되지 않았을 때만 마크다운으로 응답하세요. 와일드카드 */*는 절대 인정하면 안 됩니다. 그렇지 않으면 “무엇이든 받는다”고 말하는 브라우저, 링크 검사기, 소셜 미리보기 봇이 마크다운을 받게 됩니다.
Cloudflare로 AI 에이전트용 마크다운 제공하기
2026년 2월 12일 Cloudflare가 Markdown for Agents를 발표했습니다. 존(zone)에서 이 기능을 켜면(베타이며 Pro, Business, Enterprise 요금제에서 무료로 제공됩니다) Accept: text/markdown 요청에 HTML을 즉석에서 마크다운으로 변환해 돌려줍니다. 원본 서버는 바꾸지 않아도 됩니다.
발표문의 예시 응답은 기대할 수 있는 헤더를 보여 줍니다.
content-type: text/markdown; charset=utf-8
vary: accept
x-markdown-tokens: 725
content-signal: ai-train=yes, search=yes, ai-input=yes
이미 해당 요금제의 Cloudflare 뒤에서 사이트를 운영 중이고 변환 결과가 괜찮다면 가장 빠른 방법입니다. 의존하기 전에 curl로 결과를 확인하세요("curl로 테스트하기" 섹션 참고). 마크다운 버전의 내용을 직접 통제하고 싶거나 다른 환경에서 운영한다면 직접 구현하세요.
직접 구현하기: 짧은 Node 예시
아래 스케치에는 위의 규칙이 모두 들어 있습니다. 명시적으로 요청했을 때만 마크다운을 보내고, 두 버전 모두에 Vary: Accept를 붙이고, 협상하지 않는 클라이언트를 위해 고정 주소 /index.md를 두고, 마크다운 응답 헤더에 canonical 링크를 넣습니다. 최소한의 예시이며 운영용 코드는 아닙니다.
import http from 'node:http';
import { readFileSync } from 'node:fs';
function wantsMarkdown(accept = '') {
const weight = new Map();
for (const part of accept.toLowerCase().split(',')) {
const [range, ...params] = part.trim().split(';');
const q = params.find((p) => p.trim().startsWith('q='));
weight.set(range.trim(), q ? Number(q.trim().slice(2)) : 1);
}
const md = weight.get('text/markdown') ?? 0;
const html = weight.get('text/html') ?? weight.get('text/*') ?? weight.get('*/*') ?? 0;
return md > 0 && md >= html; // 와일드카드만으로는 절대 마크다운을 선택하지 않습니다
}
http.createServer((req, res) => {
if (req.url === '/index.md' || (req.url === '/' && wantsMarkdown(req.headers.accept))) {
res.writeHead(200, {
'Content-Type': 'text/markdown; charset=utf-8',
'Vary': 'Accept',
'Link': '<https://example.com/>; rel="canonical"',
});
return res.end(readFileSync('index.md'));
}
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Vary': 'Accept' });
return res.end(readFileSync('index.html'));
}
res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }); // 그 밖의 모든 주소는 404로 응답합니다
res.end('Not found');
}).listen(3000);
세 가지는 따로 살펴볼 만합니다.
- 두 버전 모두에 Vary. HTML 응답에도
Vary: Accept가 필요합니다. 그렇지 않으면 공용 캐시가 HTML을 저장해 두었다가 마크다운을 요청한 에이전트에게 내주거나, 그 반대가 될 수 있습니다. - 고정 주소.
/index.md는 클라이언트가 무엇을 보내든 항상 마크다운을 돌려줍니다. 에이전트나 사람이 이 주소로 링크할 수 있고, 헤더를 설정할 수 없는 환경에서도 동작합니다. SEOgrinder 자체의 seogrinder.com/index.md가 이렇게 합니다. - Canonical 헤더. 마크다운 버전은 같은 페이지의 두 번째 표현입니다. Google은 HTML이 아닌 파일에는
rel="canonical"을 HTTP 헤더로 보낼 수 있다고 문서화하고 있습니다. 마크다운 버전이 그 페이지에 속한다는 강한 신호이지만 보장은 아닙니다(Google).
마크다운 파일은 직접 쓰거나 HTML과 같은 원본에서 생성하세요. 어느 쪽이든 틀만 빼고 페이지와 같은 내용을 담아야 합니다.
Link 헤더: 에이전트에게 사이트 설명의 위치 알리기
Link 응답 헤더는 RFC 8288에 정의되어 있습니다. 관련 주소와 관계의 종류를 알리며, 예를 들면 Link: </llms.txt>; rel="describedby"입니다. describedby 관계는 등록되어 있고 의미도 잘 맞습니다. 링크된 리소스가 이 리소스를 설명한다는 뜻입니다. 응답 헤더를 읽는 클라이언트는 본문을 파싱하기 전에 사이트 설명이 어디에 있는지 알 수 있습니다.
seogrinder.com은 시작 페이지에서 이 헤더를 보내 자체 llms.txt를 가리킵니다. 마크다운 응답에서는 같은 Link 헤더에 위에서 본 canonical 관계도 쉼표로 구분해 함께 들어갑니다.
오늘날 에이전트가 이 링크를 따라가는지는 입증되지 않았습니다. 비용은 서버 설정 한 줄입니다.
Content-Signal 줄
2025년 9월 Cloudflare는 크롤러가 콘텐츠를 가져간 뒤 그것으로 무엇을 해도 되는지 밝히는 줄을 robots.txt용으로 도입했습니다.
Content-Signal: search=yes, ai-input=yes, ai-train=no
search는 색인과 스니펫, ai-input은 AI 답변에 콘텐츠를 직접 활용하는 것, ai-train은 모델의 학습이나 미세 조정을 뜻합니다. 형식은 Cloudflare 발표문과 contentsignals.org에 설명되어 있습니다. 이것은 선언일 뿐 장벽이 아닙니다. 누구도 이를 지키도록 강제되지 않습니다. Cloudflare는 콘텐츠 신호가 선호를 표현하는 것이며 기술적 대응책이 아니고, 일부 기업은 그냥 무시할 수도 있다고 밝혔습니다. 위에서 보았듯 Cloudflare의 마크다운 예시에도 content-signal 응답 헤더가 들어 있습니다.
이 줄은 AI 봇에 대한 다른 규칙과 함께 robots.txt에 넣습니다. 봇마다 그룹을 나눌 때 흔히 하는 실수를 포함한 자세한 내용은 robots.txt로 AI 크롤러 차단·허용하기에서 볼 수 있습니다. seogrinder.com의 robots.txt는 모든 크롤러와 AI 식별자 아홉 개가 공유하는 그룹 하나를 쓰며, Content-Signal: search=yes, ai-input=yes, ai-train=yes를 사용합니다.
curl로 테스트하기
에이전트가 쓸 법한 도구와 같은 도구로 확인하세요. -I 옵션은 헤더만 보여 줍니다.
curl -sI -H "Accept: text/markdown" https://example.com/
응답에서 네 가지를 보세요. 상태 코드 200, content-type: text/markdown, Accept를 포함하는 vary, 그리고 canonical 주소가 담긴 link 헤더입니다. 다음은 seogrinder.com의 결과를 관련 줄만 남기고 줄인 것입니다.
HTTP/2 200
content-type: text/markdown; charset=utf-8
vary: Accept
link: </llms.txt>; rel="describedby"; type="text/plain", <https://seogrinder.com/>; rel="canonical"
그다음 반대 방향도 확인하세요. 아래 세 가지는 모두 text/html을 돌려줘야 합니다.
curl -sI -H "Accept: text/html" https://example.com/
curl -sI -H "Accept: */*" https://example.com/
curl -sI https://example.com/
마지막으로 -H "Accept: text/markdown, text/html;q=0.8"을 보내 보세요. 마크다운이 더 높게 평가되었으므로 마크다운이 선택되어야 합니다.
SEOgrinder는 이를 어떻게 검사하나요?
SEOgrinder로 스캔한 뒤 AI 준비도 탭을 엽니다. “AI 에이전트용 검사” 아래에 일곱 줄이 있습니다. 그중 세 줄이 이 글과 관련 있고, 모두 “추가” 그룹에 들어 있습니다.
- “HTML 대신 텍스트 제공”(Markdown Negotiation):
Accept: text/markdown요청에 마크다운이 돌아오면 충족됩니다. - “에이전트를 데이터로 안내하기”(Link Headers): 응답 헤더에서 유용한 관계를 찾습니다.
- “콘텐츠 사용 방식 선언하기”(Content Signals):
ai-train,search,ai-input을 모두 아우르는 완전한Content-Signal줄을 찾습니다.
에이전트 프롬프트 복사 버튼은 충족되지 않은 항목에서는 줄에 바로 표시되고, 충족된 항목에서는 줄을 펼치면 발견된 텍스트와 함께 표시됩니다. 아직 충족되지 않은 항목의 프롬프트는 무엇을 만들어야 하는지 설명하고, curl로 현재 상태를 보여 주며, 결과를 확인할 명령을 알려 줍니다. 충족된 항목의 프롬프트는 코딩 AI에게 기존 내용을 검토하고, 필요한 것만 바꾸고, 이해하지 못하는 규칙을 지우기 전에는 먼저 묻도록 요청합니다. AI 크롤러를 허용할지 차단할지 같은 결정은 계속 여러분의 몫이며, 충족되지 않은 항목의 프롬프트 중에는 예시 값을 제안하는 것도 있습니다. 그러니 먼저 결정하고, 프롬프트를 Claude Code, Cursor, GitHub Copilot, ChatGPT에 붙여 넣기 전에 읽어 보세요. 그런 다음 다시 확인을 눌러 다시 스캔합니다. 리포트는 최대 24시간 캐시에 남으며, 다시 확인은 새로 검사를 실행합니다(시간당 몇 번까지 가능합니다).
SEOgrinder는 “추가” 그룹에 대해 솔직하게 밝힙니다. “일부 업체의 제안입니다. Google에서의 효과는 입증되지 않았습니다.” 또한 이 도구는 ChatGPT, Gemini, Perplexity가 내 브랜드를 실제로 언급하는지는 측정하지 않습니다. 기술적 토대, 곧 기계가 내 페이지에 접근해 읽을 수 있는지를 검사합니다.
들인 노력만큼 가치가 있을까요?
사이트가 무엇을 제공하느냐에 달려 있습니다. 문서, 참조 페이지, 긴 가이드, 지식 베이스는 에이전트가 구체적인 질문에 답하려고 가져가는 종류의 콘텐츠이며, 깔끔한 마크다운 버전이 거기서 쓸모가 있습니다. 페이지가 다섯 개뿐인 작은 쇼핑몰이나 동네 가게라면 그 시간을 기본기에 쓰는 편이 낫습니다. JavaScript 없이도 HTML에 들어 있는 텍스트, 검색용 봇을 들여보내는 robots.txt, 사이트맵이 먼저입니다.
Google 자체의 AI 기능에 대해서는, AI 개요나 AI 모드에 나타나기 위한 추가 요건도, 그 밖의 특별한 최적화도 필요하지 않다고 Google이 밝히고 있습니다. 자세한 내용은 Google 문서에 있습니다. 따라서 마크다운 버전은 그 기능의 전제 조건이 아닙니다. 다른 어시스턴트는 다르게 동작할 수 있지만, AI 어시스턴트가 내 페이지를 언급해 줄 것이라고 약속할 수 있는 사람은 없습니다.
자주 하는 실수
- Vary 헤더가 없는 경우.
Vary: Accept가 없으면 캐시나 CDN이 다음 방문자에게 잘못된 버전을 내줄 수 있습니다. - 헤더를 무시하는 캐시가 앞단에 있는 경우. 원본 서버만이 아니라 공개 주소로 테스트하세요.
- 브라우저에 마크다운을 보내는 경우. 검사 로직이 와일드카드
*/*를 마크다운 요청으로 처리하면 방문자는 가공되지 않은 텍스트를 보게 됩니다. 일반 브라우저로 테스트하세요. - canonical 링크가 없는 경우. 마크다운 버전이 별도의 페이지로 취급될 수 있습니다. 협상으로 제공하는 버전은 페이지와 같은 주소에 있으므로, 우리는
noindex대신 canonical 헤더를 택했습니다. - HTML과 다른 내용을 담은 마크다운 버전. 틀만 빼고 HTML 페이지와 내용을 같게 유지하세요. 검색엔진이 두 버전의 차이를 어떻게 다루는지에 대한 출처는 없으므로 둘을 똑같이 맞추는 것이 안전합니다.
- 오래된 파일. 직접 쓴
index.md가 작년의 상품 구성을 나열하고 있다면 에이전트를 잘못 이끕니다. 페이지의 원본에서 생성하거나, 점검 목록에 올려 두세요. - 비어 있는 HTML 페이지. HTML 자체에 JavaScript가 실행되기 전까지 텍스트가 없다면, AI 에이전트용 마크다운으로도 소셜 미리보기 같은 다른 클라이언트의 문제는 해결되지 않습니다. SEOgrinder는 브라우저에서만 조립되는 페이지를 짚어 줍니다.
자주 묻는 질문
AI 에이전트용 마크다운은 순위 요인인가요?
그렇다는 증거는 없습니다. 기계를 위한 제공 형식으로 보세요. 순위를 올리는 수단으로 보면 안 됩니다.
ChatGPT, Claude, Perplexity는 마크다운을 요청하나요?
Cloudflare는 Claude Code와 OpenCode 같은 코딩 에이전트가 Accept: text/markdown을 이미 보낸다고 밝혔습니다. 대형 업체의 검색 크롤러가 이를 요청한다는 문서는 없습니다. Cloudflare의 Radar 데이터는 OAI-SearchBot에 대한 마크다운 응답을 보여 주지만, 이것이 요청 헤더가 있었다는 증거는 아닙니다. 따라서 입증되지 않았습니다.
Cloudflare가 꼭 필요한가요?
아닙니다. Cloudflare는 변환을 하나의 기능으로 제공합니다(베타, Pro, Business, Enterprise 요금제). 위의 Node 스케치에서 보듯 서버 코드 몇 줄이면 충분하며, 같은 규칙을 어떤 서버나 프레임워크에도 구현할 수 있습니다.
콘텐츠 협상과 별도의 .md 주소 중 무엇을 써야 하나요?
둘 다 쓸 수 있습니다. /index.md 같은 고정 주소는 링크하고 테스트하기 쉽습니다. 협상 방식은 두 대상에게 하나의 주소를 유지해 줍니다. seogrinder.com은 시작 페이지에 두 방식을 모두 제공합니다.
일반 방문자가 마크다운 버전을 볼 일이 있나요?
와일드카드 규칙을 지키면 없습니다. 마크다운은 text/markdown이 명시적으로 적혀 있고 text/html보다 낮게 평가되지 않았을 때만 나갑니다.
다음 단계
SEOgrinder에서 무료 스캔을 실행하고 AI 준비도 탭을 엽니다. 마크다운, Link 헤더, Content Signals에 해당하는 “추가” 줄 세 개를 보고, 내 사이트가 에이전트가 읽어 가는 종류의 사이트인지 판단하세요. 그렇다면 에이전트 프롬프트를 복사해 코딩 AI에게 변경을 맡기고, curl로 결과를 확인한 뒤 다시 스캔하세요.