SOYOYU
블로그로 돌아가기기술 SEO

JavaScript SEO 렌더링 전략: React, Next.js, Vue 프레임워크별 색인 실패 패턴

Googlebot은 JS를 렌더링하지만 크롤 효율이 낮고, 네이버 Yeti는 JS 렌더링이 불안정합니다. 프레임워크별 실제 색인 실패 패턴과 해결법을 데이터로 정리합니다.

소요유2026년 4월 28일13 min read
JavaScript SEOReact SEONext.js SEOVue SEO렌더링 최적화CSR SSR SSG네이버 SEO기술 SEO

TL;DR - 핵심 요약

  • Googlebot은 JS를 렌더링하지만 크롤 효율이 크게 떨어짐 — Onely 실험에서 HTML 대비 약 9배 느린 크롤 속도 관측
  • 네이버 Yeti는 JS 렌더링을 지원하지만 효율이 낮아 SSR을 공식 권장 — 실무적으로 CSR SPA의 네이버 색인 성공률이 매우 낮음
  • Google 2025년 12월 업데이트: 비200 상태 코드 페이지는 렌더링 파이프라인에서 제외 가능
  • 안전한 아키텍처: Next.js App Router(RSC) 또는 Nuxt SSR — 단, 프레임워크만으로 SEO가 해결되지는 않음
  • CSR이 불가피하면 프리렌더링 또는 하이브리드 렌더링으로 임시 대응

JavaScript SEO, 왜 아직도 문제인가

JavaScript SEO는 "구글이 이제 JS를 잘 렌더링한다"는 말 한마디로 끝나지 않습니다.

구글이 2019년부터 에버그린 Chromium 기반 Web Rendering Service(WRS)를 사용하는 것은 맞습니다. 하지만 렌더링을 할 수 있다는 것과 효율적으로 한다는 것은 다른 문제입니다. 그리고 한국 시장에서는 네이버까지 고려해야 하기 때문에 상황이 훨씬 복잡합니다.

이 글은 실제 측정 데이터와 검색엔진별 동작 차이를 기반으로, 프레임워크 선택과 렌더링 전략이 색인에 어떤 영향을 미치는지 정리합니다.


Googlebot의 JavaScript 렌더링: 실제 데이터

Vercel/MERJ 연구 — 100,000건 크롤 분석

2024년 4월, Vercel과 MERJ Research가 nextjs.org에서 100,000건 이상의 Googlebot 요청을 분석한 연구는 현재 가장 신뢰할 수 있는 공개 데이터입니다.

출처: Vercel - How Google Handles JavaScript Throughout the Indexing Process

200 상태 코드를 반환하는 HTML 페이지는 100% 렌더링 완료 — 동적 API 호출 콘텐츠와 React Server Components 스트리밍 콘텐츠 포함

핵심은 렌더링 지연 시간입니다:

백분위렌더링 지연
25번째4초
50번째(중앙값)10초
75번째26초
90번째약 3시간
95번째약 6시간
99번째약 18시간

쿼리 스트링이 포함된 URL은 지연이 더 심합니다. 중앙값 13초, 90번째 백분위에서 약 8.5시간입니다.

주의할 점: 이 데이터는 nextjs.org라는 고권위 사이트 기준입니다. 도메인 권위가 낮은 중소 사이트는 크롤 버짓이 적기 때문에 렌더링 지연이 더 길어집니다.

Onely 연구 — HTML 대비 9배 느린 크롤

출처: Onely - Google Needs 9X More Time to Crawl JS Than HTML

Googlebot이 JavaScript 폴더의 7번째 페이지에 도달하는 데 313시간, HTML 폴더는 36시간 — 약 9배 차이

첫 번째 JS 주입 링크를 발견하는 데도 HTML 대비 2배 이상 걸렸습니다(52시간 vs 25시간).

이 차이는 페이지 수가 적은 사이트에서는 크게 느끼지 못하지만, 수천~수만 페이지를 가진 이커머스, 미디어, 프로그래매틱 SEO 사이트에서는 크롤 버짓 문제로 직결됩니다.

Google 2025년 12월 렌더링 업데이트

출처: Search Engine Journal - Google Warns Noindex Can Block JavaScript ↗ · PPC Land - Google Clarifies JavaScript Rendering for Error Pages

2025년 12월 18일, Google이 세 가지 중요한 사항을 명확히 함

  1. 비200 HTTP 상태 코드 페이지는 렌더링을 건너뛸 수 있음 — 404, 5xx 등의 페이지에서 JavaScript가 실행되지 않을 수 있습니다
  2. 초기 HTML의 noindex는 JS 실행을 차단 — 클라이언트 사이드에서 noindex를 제거해도 무효
  3. canonical 태그는 초기 HTML에 포함하는 것이 권장됨 — JS로 주입한 canonical도 렌더링 후 인식될 수 있지만, 초기 HTML에 포함하는 것이 가장 안정적

SPA에서 모든 URL에 200을 반환하는 소프트 404 패턴을 사용하면, Google이 오류 페이지를 렌더링하고 색인할 수 있습니다. 반대로 올바르게 404를 반환하면 렌더링 자체를 건너뛰므로, JS로 보여주는 대체 콘텐츠(추천 상품 등)는 보이지 않습니다.


네이버 Yeti: JS 렌더링은 가능하지만 실무적으로 불안정하다

한국에서 JavaScript SEO를 논할 때 가장 중요한 것은 네이버 Yeti의 JS 렌더링 효율 문제입니다.

출처: 네이버 서치어드바이저 - JavaScript 페이지 가이드 ↗ · 네이버 서치어드바이저 - 색인 효율 가이드

네이버 공식 문서에는 "CSR이라고 해서 크롤링이 안 되는 것은 아니지만, 크롤링 효율 면에서 SSR이 낫기 때문에 주요 콘텐츠는 SSR로 렌더링할 것"을 권장하고 있습니다.

즉, 네이버도 JavaScript를 어느 정도 처리할 수 있습니다. 하지만 실무에서의 현실은 다릅니다.

공식 지원과 실무 결과의 차이

네이버가 JS를 렌더링할 수 있다고 해서, CSR SPA가 안정적으로 색인된다는 의미는 아닙니다. 네이버 가이드에서 명시하는 주의사항:

  • JS/CSS 파일을 robots.txt로 차단하면 안 됨
  • URL에 # 프래그먼트를 사용하면 안 됨 (해시 라우팅 금지)
  • JS나 meta refresh 리다이렉트는 지원하지 않으며, HTTP 리다이렉트만 인식
  • 네이버 서치어드바이저에서 반드시 사이트를 직접 등록해야 함

실무적으로, 순수 CSR SPA 사이트가 네이버에 콘텐츠까지 제대로 색인되는 경우는 드뭅니다. 특히 초기 HTML이 <div id="root"></div> 수준으로 비어 있는 사이트에서 네이버가 JS를 실행하여 전체 콘텐츠를 읽어가는 것을 기대하기는 어렵습니다.

<!-- 순수 CSR SPA의 초기 HTML -->
<!DOCTYPE html>
<html>
<head><title>My App</title></head>
<body>
  <div id="root"></div>
  <script src="/bundle.js"></script>
</body>
</html>

이 HTML에서 네이버가 JS를 렌더링하더라도, 렌더링 효율이 낮아 모든 페이지를 안정적으로 처리한다는 보장이 없습니다. 네이버 스스로가 SSR을 권장하는 이유이기도 합니다.

한국 검색 점유율의 현실

출처: Korea Times - Naver tops 60% in Korea's search market

네이버 62.86%, 구글 29.55% (2025년 기준)

네이버 점유율이 63%라는 것이 곧 "CSR 사이트가 트래픽 63%를 잃는다"를 의미하지는 않습니다. 사이트마다 네이버/구글 유입 비율은 다릅니다. 하지만 네이버에서의 색인 불안정성을 감수할 이유가 없다는 점은 분명합니다. SSR로 전환하면 두 검색엔진 모두에서 안정적으로 작동합니다.


렌더링 전략별 비교: CSR vs SSR vs SSG vs ISR

검색엔진별 호환성 매트릭스

렌더링 전략Google 색인네이버 색인초기 로드 속도콘텐츠 신선도
CSR가능하지만 비효율적불안정 (SSR 권장)느림실시간
SSR즉시즉시보통실시간
SSG즉시즉시빠름빌드 시점
ISR즉시즉시빠름재검증 주기
RSC(서버 컴포넌트)즉시즉시빠름요청 시점

결론은 명확합니다: 한국 시장을 대상으로 하는 사이트에서 CSR 단독 사용은 SEO 관점에서 올바른 선택이 아닙니다.

각 전략의 실제 동작

SSR(Server-Side Rendering): 매 요청마다 서버에서 HTML을 생성합니다. 크롤러는 첫 번째 요청에서 완전한 HTML을 받습니다. 서버 부하가 있지만, 항상 최신 콘텐츠를 제공합니다.

SSG(Static Site Generation): 빌드 시점에 HTML을 미리 생성합니다. 가장 빠른 응답 속도. 콘텐츠 변경이 적은 페이지(회사 소개, 블로그 등)에 적합합니다.

ISR(Incremental Static Regeneration): SSG의 속도 + 주기적 콘텐츠 갱신. 상품 페이지처럼 자주 바뀌지만 실시간까지는 필요 없는 페이지에 적합합니다.

RSC(React Server Components): Next.js App Router의 기본값. 서버 컴포넌트는 서버에서만 실행되어 HTML로 전달되며, 해당 컴포넌트의 JS는 클라이언트에 전송되지 않습니다. 다만 실제 앱에서는 클라이언트 컴포넌트도 함께 사용하므로 JS 번들이 완전히 없어지는 것은 아닙니다. Vercel/MERJ 연구에서 Google이 RSC 스트리밍 콘텐츠를 정상적으로 렌더링하는 것이 확인되었습니다.


프레임워크별 SEO 실패 패턴과 해결법

React (Create React App / Vite)

문제: 기본 설정이 CSR. <div id="root"> 안의 모든 콘텐츠가 JavaScript 실행 이후에만 나타남.

실패 패턴:

  • 네이버에서 사이트 전체가 색인되지 않음
  • Google에서 색인은 되지만 신규 콘텐츠 반영이 수일~수주 지연
  • react-helmet으로 설정한 메타 태그가 크롤러에 보이지 않을 수 있음

해결법:

  • Next.js로 마이그레이션 (권장)
  • React Router + 프리렌더링 서비스(Prerender.io 등) 도입
  • 최소한 메타 태그와 핵심 콘텐츠는 서버에서 렌더링

Next.js (Pages Router → App Router)

Next.js는 기본적으로 서버 렌더링을 제공하므로 React 단독보다 SEO 친화적입니다. 하지만 함정이 있습니다.

Pages Router 주요 함정:

  • getStaticPaths에서 fallback: true 사용 시, 첫 방문 크롤러에게 로딩 상태가 노출
  • 동적 import로 핵심 콘텐츠를 지연 로딩하면 크롤러에 보이지 않음

App Router 주요 함정:

  1. generateMetadata fetch 실패 시 빈 title: 비동기 데이터 패칭이 실패하면 메타데이터가 빈 상태로 렌더링됩니다. Search Console에서 중복 title 이슈로 나타남
// 위험한 패턴 — fetch 실패 시 빈 title
export async function generateMetadata({ params }) {
  const post = await fetchPost(params.slug); // 실패 가능
  return { title: post.title }; // undefined
}

// 안전한 패턴 — fallback 포함
export async function generateMetadata({ params }) {
  const post = await fetchPost(params.slug).catch(() => null);
  return { 
    title: post?.title ?? '기본 페이지 제목 | 사이트명' 
  };
}
  1. searchParams 사용이 정적 생성을 무력화: searchParams를 읽는 순간 해당 페이지는 동적 렌더링으로 전환됩니다. 의도치 않게 빌드 타임 최적화를 잃게 됩니다.

  2. 404 상태 코드와 notFound() 처리: 존재하지 않는 페이지에서 200을 반환하는 "소프트 404" 문제는 Next.js 사이트에서 흔히 발생합니다. Google은 이를 소프트 404로 감지하거나, 의도하지 않은 에러 페이지를 색인할 수 있습니다.

// 올바른 404 처리
import { notFound } from 'next/navigation';

export default async function Page({ params }) {
  const data = await fetchData(params.slug);
  if (!data) notFound(); // 404 상태 코드 반환
  return <Article data={data} />;
}
  1. 'use client' 컴포넌트의 콘텐츠: 클라이언트 컴포넌트는 서버에서도 프리렌더링되므로 초기 HTML에 포함됩니다. 하지만 하이드레이션 실패 시 React가 DOM 전체를 재구축하면서 콘텐츠가 일시적으로 사라질 수 있습니다.

Vue / Nuxt

Vue SPA 문제(CSR): React와 동일합니다. 네이버에서 보이지 않고, Google에서도 렌더링 지연.

Nuxt SSR/SSG 사용 시 주의점:

  • asyncData/useFetch에서 에러 처리 누락 시 빈 페이지 렌더링
  • <NuxtLink>가 아닌 일반 <a> 태그 사용 시 클라이언트 네비게이션이 깨지고 전체 페이지 리로드
  • useHead() 컴포저블로 메타 태그 설정 시, 서버/클라이언트 불일치 주의

Nuxt 3 권장 설정:

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true, // SSR 활성화 (기본값이지만 명시 권장)
  routeRules: {
    '/blog/**': { prerender: true }, // 블로그는 SSG
    '/products/**': { swr: 3600 },   // 상품은 ISR (1시간)
    '/dashboard/**': { ssr: false },  // 대시보드만 CSR
  }
})

하이드레이션 오류가 SEO에 미치는 영향

하이드레이션(Hydration)은 서버에서 생성한 HTML에 클라이언트 JavaScript를 연결하는 과정입니다. 서버 HTML과 클라이언트 HTML이 다르면 하이드레이션 불일치(mismatch) 오류가 발생합니다.

출처: Niko Alho - Hydration Latency is Bleeding Revenue

하이드레이션이 실패하면 React는 전체 DOM을 파괴하고 처음부터 재구축합니다. 이 과정에서 렌더링 비용이 2배가 됩니다.

하이드레이션 중단 시 Google이 색인할 수 있는 상태:

  • 주요 H1 태그가 없는 페이지
  • 내부 링크가 마운트되지 않은 상태
  • Schema/구조화 데이터가 주입되지 않은 상태
  • canonical 태그가 해석되지 않은 상태

성능 영향: 하이드레이션 불일치는 INP(Interaction to Next Paint) 지표를 악화시킵니다. INP는 2024년 3월부터 Core Web Vitals의 공식 지표이며 직접적인 순위 요인입니다.

흔한 원인과 해결법:

원인해결 방법
서버/클라이언트 시간대 차이suppressHydrationWarning 또는 useEffect로 클라이언트 전용 렌더링
브라우저 확장 프로그램이 DOM 수정하이드레이션 에러 로그 모니터링, 사용자 환경 차이 감안
조건부 렌더링(typeof window)useEffect 내에서 클라이언트 전용 로직 분리
서버/클라이언트 데이터 불일치서버 데이터를 __NEXT_DATA__로 전달하여 일치 보장

실전 체크리스트: JavaScript 사이트 SEO 진단

사이트의 JavaScript SEO 상태를 직접 진단할 수 있는 체크리스트입니다.

1단계: 렌더링 상태 확인

Google Search Console — 가장 정확한 방법:

  • URL 검사 → "실시간 테스트" — Google이 실제로 렌더링한 HTML을 확인할 수 있음
  • 페이지 색인 생성 보고서 → "색인이 생성되지 않은 페이지" 목록 확인
  • site: 검색 연산자는 참고용으로만 사용 (정확한 색인 수를 반영하지 않음)

네이버 서치어드바이저:

  • 웹 페이지 수집 → 수집 현황에서 색인된 페이지 확인
  • URL 검사 기능으로 개별 페이지 색인 상태 확인
  • 네이버 색인 수가 Google보다 현저히 적으면 JS 렌더링 문제 가능성 높음

초기 HTML 확인 — 첫 번째 패스 테스트:

# JavaScript 실행 없이 서버가 반환하는 원본 HTML 확인
curl -s https://yourdomain.com | grep -i "<title\|<h1\|<meta"

이 테스트에서 콘텐츠가 보이지 않는다고 해서 Google이 색인하지 못하는 것은 아닙니다. Google은 JS를 렌더링할 수 있기 때문입니다. 하지만 네이버에서는 이 초기 HTML이 색인의 기본이 되므로, 여기에 핵심 콘텐츠가 없으면 네이버 색인에 문제가 생길 가능성이 높습니다.

2단계: 프레임워크별 점검 항목

점검 항목React SPANext.jsNuxt/Vue SSR
초기 HTML에 콘텐츠 포함확인 필수기본 포함ssr:true 확인
메타 태그 서버 렌더링react-helmet-asyncgenerateMetadatauseHead
404 상태 코드 올바른 반환서버 설정 필요notFound() 사용error.vue 확인
내부 링크 <a href> 존재router-link 확인Link 컴포넌트NuxtLink
robots.txt에서 JS 번들 허용Disallow 없는지 확인동일동일

3단계: 네이버 전용 점검

  • 네이버 서치어드바이저에 사이트 등록 여부
  • XML 사이트맵 제출 여부
  • curl로 확인한 초기 HTML에 한국어 콘텐츠 포함 여부
  • Open Graph 태그에 한국어 title/description 포함 여부
  • HTTP 301 리다이렉트 사용 여부 (JS/meta refresh 리다이렉트 사용 안 함)

권장 아키텍처: 한국 시장용

React 프로젝트

신규 프로젝트: Next.js App Router 사용. 서버 컴포넌트가 기본값이므로 렌더링 측면에서 유리하지만, 올바른 상태 코드 반환, 메타데이터 설정, 사이트맵 제출 등은 별도로 챙겨야 합니다.

기존 CRA/Vite 프로젝트: Next.js 마이그레이션이 어려우면 프리렌더링 서비스 도입을 우선 검토.

Vue 프로젝트

신규 프로젝트: Nuxt 3 사용. routeRules로 페이지 유형별 렌더링 전략 분리.

기존 Vue SPA: Nuxt 마이그레이션 또는 vite-plugin-ssr 검토.

공통 원칙

  1. SEO가 중요한 페이지는 반드시 서버 렌더링 — 홈, 상품, 블로그, 랜딩 페이지
  2. 인증이 필요한 페이지만 CSR — 대시보드, 마이페이지, 관리자
  3. 메타 태그와 canonical은 서버에서 설정하는 것이 가장 안정적 — Google은 JS 렌더링 후에도 인식하지만, 네이버 안정성과 일관성을 위해 초기 HTML에 포함 권장
  4. 네이버 서치어드바이저 등록은 필수 — 자동 발견에 의존하지 않음

자주 묻는 질문

Q1: Google이 JavaScript를 렌더링한다면, SSR이 꼭 필요한가요?

Google은 JS를 렌더링할 수 있지만, Onely의 실험에서 HTML 대비 약 9배 느린 크롤 속도가 관측되었습니다. 이 수치는 특정 실험 조건의 결과이며 모든 사이트에 동일하게 적용되지는 않지만, JS 렌더링에 추가 비용이 든다는 점은 분명합니다. 페이지 수가 적은 사이트에서는 큰 차이가 없을 수 있지만, 수백~수천 페이지 규모에서는 신규 콘텐츠 색인이 지연될 수 있습니다. 또한 한국 시장에서는 네이버의 JS 렌더링이 불안정하므로, SSR 또는 SSG가 실질적으로 필요합니다.

Q2: 네이버도 JavaScript를 렌더링한다는 말을 들었는데요?

네이버 공식 가이드에는 "CSR이라고 해서 크롤링이 안 되는 것은 아니지만, 크롤링 효율 면에서 SSR이 낫다"고 명시되어 있습니다. 네이버도 JS를 어느 정도 처리할 수 있지만, 렌더링 효율이 낮아 모든 CSR 페이지를 안정적으로 색인한다고 보기 어렵습니다. 특히 # 해시 라우팅, JS 리다이렉트 등은 명시적으로 지원하지 않습니다. 주요 콘텐츠는 초기 HTML에 포함시키는 것이 안전합니다.

Q3: Dynamic Rendering(동적 렌더링)은 어떤가요?

Google은 동적 렌더링 관련 가이드를 더 이상 권장하지 않으며, 장기적 해결책이 아닌 임시 방편으로 간주합니다. 크롤러에게만 다른 HTML을 제공하는 방식은 클로킹 위험이 있고, 유지보수 비용도 높습니다. SSR이나 SSG로 전환하는 것이 올바른 방향입니다.

Q4: React Server Components(RSC)는 SEO에 어떤 영향이 있나요?

RSC의 서버 컴포넌트 부분은 서버에서만 실행되어 HTML로 전달되며, 해당 컴포넌트의 JS는 클라이언트에 전송되지 않습니다. 다만 실제 앱에서는 클라이언트 컴포넌트('use client')도 함께 사용하므로 JS 번들이 완전히 사라지는 것은 아닙니다. Vercel/MERJ 연구에서 Google이 RSC 스트리밍 콘텐츠를 정상적으로 렌더링하는 것이 확인되었습니다. 네이버 입장에서도 초기 HTML에 콘텐츠가 포함되므로 유리합니다. 현재 SEO 관점에서 가장 안전한 React 아키텍처이지만, 메타데이터 설정, 상태 코드 처리 등은 여전히 개발자가 챙겨야 합니다.

Q5: 이미 CSR로 만든 사이트인데, 마이그레이션 없이 할 수 있는 것은?

프리렌더링 서비스(Prerender.io 등)를 통해 크롤러에게 미리 렌더링된 HTML을 제공할 수 있습니다. 완전한 해결책은 아니지만, SSR 전환 전 임시 대응으로 유효합니다. 최소한 주요 랜딩 페이지와 상품 페이지의 메타 태그를 서버에서 설정하고, 사이트맵을 네이버 서치어드바이저에 제출하세요.


마무리

JavaScript SEO의 핵심은 단순합니다. 크롤러가 첫 번째 요청에서 콘텐츠를 볼 수 있는가? 이 질문에 "예"라고 답할 수 있으면 대부분의 문제는 해결됩니다.

한국 시장에서는 Google뿐 아니라 네이버까지 고려해야 하므로, 서버 렌더링은 선택이 아니라 기본값이어야 합니다. Next.js App Router나 Nuxt 3를 사용하면 렌더링 측면에서 좋은 출발점이 되지만, 프레임워크 선택만으로 SEO가 완성되지는 않습니다. 올바른 상태 코드, 메타데이터, 사이트맵, 서치어드바이저 등록까지 함께 챙겨야 합니다.

이미 CSR SPA를 운영 중이라면, 지금 curl로 초기 HTML을 확인해 보세요. 핵심 콘텐츠가 보이지 않는다면, 네이버에서의 색인이 불안정할 가능성이 높습니다.

JavaScript SEO 진단이 필요하시면 XEO 무료 진단을 신청하세요.

검색 최적화가 필요하신가요?

무료 상담을 통해 비즈니스에 맞는 최적화 전략을 확인하세요.