콘텐츠로 이동

LLM 검색 최적화

BreezeBio는 AI 기반 검색 서비스(ChatGPT, Claude, Perplexity 등)에서 콘텐츠가 정확하게 인덱싱되도록 LLM SEO 최적화가 구현되어 있습니다.

요소설명파일 위치
llms.txtLLM용 사이트 콘텐츠 마크다운LlmsTxtGenerator.php
robots.txtAI 크롤러 허용 설정web/robots.txt
Schema.orgOrganization JSON-LDbase.twig
SEO 폴백Svelte 블록 서버사이드 HTML.seo-content 패턴

위치: web/app/themes/genedit/src/LlmsTxt/LlmsTxtGenerator.php

namespace Genedit\LlmsTxt;
class LlmsTxtGenerator
{
public function register(): void
{
add_action('rest_api_init', [$this, 'registerRoutes']);
add_action('init', [$this, 'addRewriteRules']);
add_action('template_redirect', [$this, 'handleRewrite']);
}
}
URL설명캐시
/llms.txt요약 버전1시간
/llms-full.txt전체 콘텐츠1시간
/wp-json/genedit/v1/llms.txtREST API (요약)1시간
/wp-json/genedit/v1/llms-full.txtREST API (전체)1시간
public function addRewriteRules(): void
{
add_rewrite_rule('^llms\.txt$', 'index.php?llms_txt=1', 'top');
add_rewrite_rule('^llms-full\.txt$', 'index.php?llms_full_txt=1', 'top');
}

주의: Rewrite rule 추가 후 ddev wp rewrite flush 필요

public function generate(bool $full = false): string
{
// 1. 사이트 정보
$siteName = get_bloginfo('name');
$siteDescription = get_bloginfo('description');
// 2. 네비게이션 메뉴 (primary 메뉴)
$menuItems = wp_get_nav_menu_items($menuLocations['primary']);
// 3. 발행된 페이지
$pages = get_posts(['post_type' => 'page', 'post_status' => 'publish']);
// 4. 뉴스(포스트)
$posts = get_posts(['post_type' => 'post', 'posts_per_page' => $full ? 50 : 20]);
// 마크다운 형식으로 출력
}
private function getCleanContent(\WP_Post $post): string
{
$content = $post->post_content;
// Gutenberg 블록 코멘트 제거
$content = preg_replace('/<!--.*?-->/s', '', $content);
// 헤딩 변환
$content = preg_replace('/<h1[^>]*>(.*?)<\/h1>/is', '# $1', $content);
$content = preg_replace('/<h2[^>]*>(.*?)<\/h2>/is', '## $1', $content);
// 리스트 변환
$content = preg_replace('/<li[^>]*>(.*?)<\/li>/is', '- $1', $content);
// 링크 변환
$content = preg_replace('/<a[^>]*href=["\']([^"\']*)["\'][^>]*>(.*?)<\/a>/is', '[$2]($1)', $content);
// 나머지 HTML 태그 제거
$content = wp_strip_all_tags($content);
return trim($content);
}

위치: web/robots.txt

# AI Crawlers - Allowed
User-agent: GPTBot
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: Claude-Web
Allow: /
User-agent: anthropic-ai
Allow: /
User-agent: Amazonbot
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: YouBot
Allow: /
# LLM 표준
LLMs-Txt: https://breezebio.com/llms.txt
Sitemap: https://breezebio.com/sitemap.xml
크롤러User-Agent서비스
GPTBotGPTBot/1.0 (+https://openai.com/gptbot)OpenAI ChatGPT
ClaudeBotClaudeBot/1.0Anthropic Claude
PerplexityBotPerplexityBot/1.0Perplexity AI
AmazonbotAmazonbot/0.1Amazon Alexa

위치: web/app/themes/genedit/templates/base.twig

<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "{{ site.name }}",
"url": "{{ site.url }}",
"description": "{{ site.description }}",
"logo": "{{ theme_uri }}/static/images/logo.svg",
"sameAs": [
"https://www.linkedin.com/company/breezebio"
]
}
</script>

필요시 추가 가능한 스키마:

{
"@type": "Organization",
"founder": {
"@type": "Person",
"name": "..."
},
"foundingDate": "2023",
"numberOfEmployees": {
"@type": "QuantitativeValue",
"value": 50
}
}

Svelte 컴포넌트는 CSR로 렌더링되어 검색엔진/AI 크롤러가 콘텐츠를 인덱싱할 수 없음.

서버사이드에서 .seo-content 영역에 시맨틱 HTML 제공:

{# blocks/genedit-hero/hero.twig #}
<div id="{{ block_id }}" class="{{ block_class }}">
<div data-svelte="hero"
data-title="{{ fields.title|e('html_attr') }}">
{# SEO 폴백 - Svelte 마운트 후 숨김 #}
<div class="seo-content">
<h1>{{ fields.title }}</h1>
<p>{{ fields.body|raw }}</p>
</div>
</div>
</div>
<script>
import { onMount } from 'svelte';
onMount(() => {
// .seo-content 숨김
const seoContent = document.querySelector('.seo-content');
if (seoContent) {
seoContent.style.display = 'none';
}
});
</script>

Terminal window
# 요약 버전
$ curl https://breezebio.com/llms.txt
# 전체 버전
$ curl https://breezebio.com/llms-full.txt
# REST API
$ curl https://breezebio.com/wp-json/genedit/v1/llms.txt
Terminal window
$ curl https://breezebio.com/robots.txt | grep -A2 "GPTBot"
Terminal window
# 서버 로그에서 AI 크롤러 접근 확인
$ grep -E "GPTBot|ClaudeBot|PerplexityBot" /var/log/nginx/access.log

header('Cache-Control: public, max-age=3600'); // 1시간

llms.txt는 WordPress 콘텐츠 기반으로 동적 생성되므로:

  1. 콘텐츠 변경 → 캐시 만료 후 자동 반영
  2. 즉시 반영 필요 시 → 서버 캐시 삭제
Terminal window
# Nginx 캐시 삭제 (서버 설정에 따라 다름)
# 또는 Cloudflare 캐시 Purge

기능설명우선순위
다국어 llms.txt언어별 /ko/llms.txt 제공
llms.txt 커스텀 섹션제품, 파이프라인 정보 추가
Article 스키마뉴스 포스트에 Article JSON-LD낮음
FAQ 스키마FAQ 페이지에 FAQPage JSON-LD낮음