Free

Claude로 Rails 사이트를 AI 네이티브로 만들기

사람과 AI 에이전트를 동시에 대응하는 사이트를 위한 6가지 실전, 복사해 쓸 수 있는 체크리스트 포함


지난 4일 동안, Claude Code와 함께 smarts.md를 "사람이 읽는 스마트 계약 문서 사이트"에서 "AI 에이전트가 사용하는 스마트 계약 문서 사이트"로 바꿨습니다.

같은 일처럼 들리지만 실제로는 꽤 다릅니다. 사람을 위한 사이트는 가독성, 검색성, 로딩 속도를 최적화합니다. AI 에이전트를 위한 사이트는 다른 질문에 답해야 합니다.

  • AI 크롤러가 도달할 수 있는가 (기본 robots.txt가 차단하고 있지는 않은가)
  • HTML을 렌더링하지 않고도 깨끗한 콘텐츠를 뽑아낼 수 있는가
  • "문서를 읽지" 않고도 당신의 도구를 호출할 수 있는가
  • 각 페이지가 AI에게 "어떻게 참조하고, 어떻게 질의하는지"를 알려주는가

Claude에게 만들게 한 6가지 장치를 소개합니다. 모두 독립적으로 당신의 사이트에 옮길 수 있습니다.

1. robots.txt로 AI 크롤러를 명시적으로 환영하기

대부분 사이트의 robots.txt는 오래된 템플릿에서 복사된 것이고, 모르는 User-Agent는 암묵적으로 차단합니다. 하지만 2025년 이후 많은 AI 크롤러는 새로 생긴 User-Agent입니다 — GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent 등. 이들에게 열어두려면 명시적으로 Allow를 해야 합니다.

smarts의 robots.txt는 첫머리에 정책 선언을 하고, 이어서 User-agent + Allow: /를 12개 나열해 OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta, Cohere를 커버합니다. 태도는 단순 명료합니다 — 이 사이트는 AI에게 읽히기 위해 존재합니다.

2. llms.txt — LLM을 위한 메뉴

llms.txtllmstxt.org가 제안한 관습입니다. 사이트 루트에 간결한 Markdown을 놓고, LLM에게 "이 사이트는 무엇인지, 어떻게 사용하는지, 주요 진입점은 어디인지"를 알려줍니다. 사이트의 엘리베이터 피치 같은 겁니다.

smarts의 llms.txt는 약 60줄이고, 이런 내용을 담습니다.

  • 한 줄 포지셔닝 (Live docs for every verified smart contract)
  • AI 에이전트에서 사용하는 법 (MCP 엔드포인트, 한 줄 설정 명령)
  • URL 규칙 (/{chain}/{address} vs 짧은 slug)
  • MCP 도구 목록과 한 문장 설명
  • 큐레이트된 계약 목록 (LLM의 "기본 답" 용)
  • 범위와 제한 (지원하지 않는 체인, 캐싱 정책)

핵심 통찰: LLM은 문서를 토큰으로 읽기 때문에 사이트 전체를 크롤하지 않습니다. 증류된 인덱스를 건네주면 적중률이 확 올라갑니다.

3. .well-known/mcp.json — 미리 베팅

MCP 프로토콜은 아직 /.well-known/openid-configuration 같은 자동 발견 관습을 확립하지 못했습니다. 오늘 고정된 경로를 크롤하는 공개 클라이언트는 없습니다.

그래도 매니페스트를 공개하는 건 30줄짜리 일입니다.

def well_known_mcp
  response.set_header("Cache-Control", "public, max-age=3600")
  response.set_header("Access-Control-Allow-Origin", "*")
  render json: {
    name: "smarts",
    version: "0.1.0",
    description: "...",
    protocol_version: "2024-11-05",
    transports: [{ type: "sse", endpoint: "https://smarts.md/mcp/sse" }],
    capabilities: { tools: true, resources: false, prompts: false },
    tools: MCP_TOOLS.map { |t| { name: t[:name], description: t[:blurb] } }
  }
end

어떤 발견 관습이 확립되는 순간 한 줄도 바꾸지 않고 합류할 수 있습니다. 동시에 이 매니페스트는 개발자 대상 자기 문서화이기도 합니다 — MCP가 어떻게 생겼는지 궁금한 사람은 curl smarts.md/.well-known/mcp.json이면 충분합니다.

핵심은 tools 배열이 MCP_TOOLS 상수에서 파생된다는 것, 단일 진실 소스입니다. 기존 구조 테스트가 모든 app/tools/*_tool.rb가 그 상수에 나타나도록 강제하므로, 매니페스트는 "새 도구를 빠뜨리지 않는다"는 보장을 공짜로 상속받습니다.

4. .md 변형: 모든 페이지에 WebFetch 친화적 증류판

이게 제일 만족스러운 부분입니다. Claude Code의 WebFetch 도구는 HTML을 받고 나서 스스로 정리하고 내용을 뽑아내야 하는데, 토큰 소비가 많고 불안정합니다. 그런데 처음부터 .md를 제공하면 어떨까요?

Rails의 respond_to가 기본 지원합니다.

# config/routes.rb
get ":slug(.:format)", to: "contracts#show",
    constraints: { slug: ContractSlugs::ROUTE_PATTERN, format: /html|md/ }

https://smarts.md/usdc-eth는 HTML을 반환하고, https://smarts.md/usdc-eth.md는 40줄짜리 Markdown을 반환합니다 — 주소, 체인, 분류, MCP 엔드포인트, AI 에이전트로 질의하는 법, 원본 링크.

# USD Coin on Ethereum

- **Address:** `0xa0b8...`
- **Chain:** Ethereum
- **Classification:** ERC-20 Token

## Query via AI agent

- **MCP endpoint:** `https://smarts.md/mcp/sse`
- **Reference:** `usdc-eth`
- **Sample prompt:** "Tell me the current state of usdc-eth"

AI 에이전트가 .md를 한 번 가져오면 원하는 구조화 정보가 전부 들어 있고 DOM 파서도 필요 없습니다. 이건 Claude가 빨리 해냈습니다 — controller 하나, .md.erb 템플릿 두 개, routes에 (.:format) 추가, 그게 전부.

5. 페이지 안의 MCP 카드: 사용자가 자기 AI를 이 페이지로 가리키게 하기

이건 역방향의 발견입니다. 제 사이트 방문자 중 이미 Claude Code / Cursor / Windsurf를 쓰는 사람들이 일정 비율 있습니다. 계약 페이지를 보고 나면 대개 "내 AI한테 이거 한번 물어보자"가 다음 행동입니다.

그래서 각 계약 페이지에 카드를 렌더링합니다.

  • Reference: 큐레이트된 slug (예: usdc-eth) 또는 chain/address, 옆에 복사 버튼
  • Sample prompt: "Tell me the current state of usdc-eth", 옆에 복사 버튼
  • MCP 아직 안 연결한 사람에게: mcp.smarts.md 링크 (한 줄 설정)

"이 계약을 보고 있다"에서 "내 AI에게 묻고 있다"까지 클릭 한 번의 마찰. 카드는 DaisyUI 카드와 범용 Stimulus copy 컨트롤러로 erb 50줄, 거기에 회귀 테스트가 data-copy-text-value 속성을 고정해 미래의 refactor가 사용자 클립보드에 잘못된 문자열을 조용히 붙이지 못하게 합니다.

6. 전통적인 SEO: 다만 schema.org를 제대로 쓰기

OpenGraph, Twitter Card, JSON-LD — 전통 검색과 소셜 카드용 레이어지만, 할 가치가 있습니다. AI 크롤러도 여기를 읽으니까요.

흥미로운 선택은 JSON-LD가 스마트 계약을 어떻게 기술해야 하는가입니다. Claude는 WebPageSoftwareApplication을 감싸는 형태를 택했습니다.

{
  "@type": "WebPage",
  "about": {
    "@type": "SoftwareApplication",
    "name": "USD Coin",
    "applicationCategory": "SmartContract",
    "operatingSystem": "Ethereum",
    "identifier": "0xa0b8..."
  }
}

operatingSystem엔 체인 이름, identifier엔 주소, additionalType엔 분류 (예: "Uniswap V3 Pool"). schema.org에는 전용 SmartContract 타입이 없지만, SoftwareApplication + 이 필드들이면 LLM이 "Ethereum에서 돌아가는, 주소로 식별되는 계약"이라고 이해하기에 충분합니다.

OG 이미지는 1200×630 summary_large_image, Twitter Card, 브레드크럼, softwareVersion, license 필드도 같이 채웠습니다.

전부 합치면 얼마나 큰 작업일까

위 6개 항목은 4일 동안 7개의 PR에 들어갔습니다.

PR 파일 수 크기
feat/ai-crawler-discovery 2 ~126줄
feat/well-known-mcp-manifest 4 ~129줄
feat/markdown-contract-pages 6 ~298줄
feat/contract-mcp-card 3 ~126줄
feat/seo-meta-tags 8 ~292줄
feat/seo-enrichments 8 ~189줄
feat/og-card

각각이 독립된 PR, 독립된 테스트, 독립된 커밋 메시지입니다. 이 잘게 나누는 리듬이 Claude와 협업하는 데서 가장 가치 있는 부분입니다 — 각 PR은 한눈에 diff를 훑을 수 있는 크기를 유지하면서, 쌓아놓고 보면 사이트에 완전한 AI 대응 면이 생겨 있습니다.

바로 복사해 쓸 수 있는 체크리스트

콘텐츠형 사이트를 AI 친화적으로 만들고 싶다면 이 순서로 하세요.

  1. robots.txt에서 주요 AI 크롤러를 명시적으로 Allow
  2. /llms.txt를 작성 (증류된 메뉴)
  3. 핵심 콘텐츠 페이지에 .md 변형 추가
  4. MCP 서버가 있으면 /.well-known/mcp.json 공개
  5. 콘텐츠 페이지에 "이 페이지에 대해 AI에게 물어보기" 카드를 배치
  6. JSON-LD / OpenGraph를 콘텐츠 종류에 맞는 schema.org 타입으로 채우기

앞의 5개는 대부분의 SEO 엔지니어가 말해주지 않습니다 — 전통 SEO 플레이북에 없기 때문입니다. 하지만 제 4일치 데이터를 보면 AI 트래픽 곡선과 사람 트래픽 곡선은 완전히 독립된 두 선입니다. 둘 다 돌봐야 합니다.