Citeon
플랫폼·기술

서버 사이드 렌더링과 AI 색인의 관계

박도현
박도현 · AEO 리서처

GPTBot·CCBot·ClaudeBot·PerplexityBot 등 주요 AI 크롤러는 JavaScript를 실행하지 않고 초기 HTTP 응답 HTML만 파싱한다. 클라이언트 사이드 렌더링(CSR) SPA가 서버에서 <div id="root"></div>만 반환하면 AI 크롤러 시점에 본문이 없는 것과 같다. 서버 사이드 렌더링(SSR)은 요청 시 완성된 HTML을 반환해 이 접근성 문제를 해소하지만, 이것이 AI 답변 인용으로 자동 이어지는 충분조건은 아니다. AI 검색의 RAG 파이프라인에서 페이지가 retrieval 풀에 포함되려면 접근성 외에 구조화 데이터·콘텐츠 밀도·도메인 신호가 함께 갖춰져야 한다.

AI 크롤러의 HTML 파싱 메커니즘

렌더링 방식별 AI 색인 가용성 비교

항목 CSR (SPA) SSR SSG / ISR
초기 HTML 텍스트 밀도 거의 없음 완전 완전
JSON-LD 파싱 보장 불확실 (JS 의존) 보장 보장
AI 학습 크롤 적합성 불리 유리 유리 (갱신 지연 주의)
실시간 RAG 검색 적합성 불리 유리 revalidate 주기 의존
구현 복잡도 낮음 높음 중간

구현: robots.txt AI 크롤러 세분화 및 캐시 헤더

robots.txt — AI 크롤러별 경로 분리

단일 User-agent: *로 모든 크롤러를 일괄 제어하면 AI 학습 차단과 실시간 RAG 허용을 구분할 수 없다. 아래와 같이 크롤러 계열별로 분리 선언한다.

# /public/robots.txt

# AI 학습 데이터 수집 크롤러
User-agent: GPTBot
Allow: /blog/
Allow: /docs/
Disallow: /admin/
Disallow: /user/
Disallow: /api/

User-agent: CCBot
Allow: /blog/
Disallow: /

User-agent: ClaudeBot
Allow: /

User-agent: Google-Extended
Allow: /

# 실시간 RAG 검색 크롤러 (전면 허용 권장)
User-agent: PerplexityBot
Allow: /

User-agent: OAI-SearchBot
Allow: /

# 크롤 빈도 힌트 (지원 크롤러 한정)
Crawl-delay: 10

Sitemap: https://example.com/sitemap.xml

Next.js — Cache-Control 헤더 및 JSON-LD 서버 삽입

SSR 페이지의 캐시 정책이 잘못 설정되면 크롤러가 구버전 HTML을 반복 수집한다. 아래는 Next.js App Router에서 블로그 경로에 캐시 헤더를 설정하고 JSON-LD를 서버 컴포넌트에서 직렬화하는 패턴이다.

// next.config.js — AI 크롤러용 캐시 헤더
/** @type {import('next').NextConfig} */
const nextConfig = {
  async headers() {
    return [
      {
        source: '/blog/:slug*',
        headers: [
          {
            key: 'Cache-Control',
            // 1시간 서버 캐시, 하루 stale-while-revalidate
            value: 'public, s-maxage=3600, stale-while-revalidate=86400',
          },
          { key: 'X-Robots-Tag', value: 'index, follow' },
        ],
      },
    ];
  },
};

module.exports = nextConfig;

// app/blog/[slug]/page.tsx (서버 컴포넌트 — JS 없이 HTML에 직렬화)
export default async function BlogPost({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.slug}`, {
    next: { revalidate: 3600 },
  }).then((r) => r.json());

  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'Article',
    headline: post.title,
    description: post.description,
    datePublished: post.publishedAt,
    dateModified: post.updatedAt,
    author: { '@type': 'Person', name: post.author },
  };

  // 서버에서 직렬화 — 크롤러는 이 JSON-LD를 초기 HTML에서 바로 읽는다
  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      <article>{post.content}</article>
    </>
  );
}

검증 및 측정

흔한 오해 — "SSR로 전환하면 AI 인용이 즉시 증가한다"

SSR은 AI 크롤러가 페이지 텍스트에 접근할 수 있는 필요조건이지 충분조건이 아니다. RAG retrieval은 텍스트 접근성 외에 쿼리-콘텐츠 임베딩 유사도, 도메인 권위도, datePublished 신선도, FAQPage·HowTo 스키마 유무를 복합적으로 평가한다. SSR 전환 후에도 인용률이 변하지 않는다면 콘텐츠 구조화 데이터를 점검해야 한다. 올바른 처리법은 SSR 전환과 동시에 핵심 페이지에 Article·FAQPage Schema.org 타입을 서버 컴포넌트에서 직접 삽입하고, curl 시뮬레이션으로 구조화 데이터가 초기 HTML에 포함됐는지 배포마다 검증하는 것이다.

기술적 FAQ

Next.js ISR(Incremental Static Regeneration)은 AI 크롤러에게 SSR과 동일하게 작동하나요?

revalidate 주기 이내라면 CDN이 캐시된 완성 HTML을 반환하므로 크롤러 입장에서는 SSG와 동일하다. 문제는 revalidate가 만료되기 전에 크롤러가 방문할 경우 구버전 HTML을 수집한다는 점이다. 콘텐츠 갱신이 잦은 페이지(뉴스·실시간 데이터)는 ISR 대신 cache: 'no-store' SSR을 적용하고, Cache-Control: s-maxage=3600, stale-while-revalidate=86400 헤더로 크롤러에게 신선도를 명시하는 것이 권장된다.

React Server Components(RSC)만으로 구성한 페이지도 CSR처럼 AI 색인에서 불리한가요?

RSC는 서버에서 HTML 스트림으로 직렬화돼 응답하므로 초기 HTML에 콘텐츠가 포함되며 CSR과 다르다. 단, 'use client' 컴포넌트가 마운트 후 별도 fetch로 채우는 동적 구역(댓글·사용자 피드·개인화 영역)은 초기 HTML에 없으므로 AI 색인에서 누락된다. 해당 데이터가 AI 색인에 중요하다면 서버 컴포넌트로 리팩토링하거나, Suspense fallback 대신 서버에서 직접 데이터를 전달하는 방식으로 변경해야 한다.

참고 자료

이 글의 권고는 아래 공식 문서·연구를 근거로 합니다.

박도현
박도현 · AEO 리서처

생성형 검색·LLM 인용에 관한 논문과 데이터를 읽고 실무 언어로 옮깁니다. 근거 없는 '카더라'를 싫어합니다.

내 사이트의 AI 검색 점수가 궁금하다면

30초 무료 진단으로 SEO·AEO·GEO 점수와 처방을 받아보세요.

무료 진단 시작
← 블로그 목록으로