Google은 JavaScript를 실행할 수 있지만 이에 의존하는 모든 페이지와 콘텐츠가 색인된다는 보장은 없습니다. 중요한 콘텐츠는 가져올 수 있어야 하고 렌더링 결과에 나타나며 일관된 색인 신호를 제공해야 합니다. 렌더링 문제인지, 발견 문제인지, 다른 원인인지 판단하기 전에 서버 응답, 브라우저 결과, Google 검사 결과를 비교합니다.
공개 콘텐츠는 서버 렌더링이나 정적 생성으로 텍스트와 링크가 존재하기까지 필요한 단계를 줄이면 전달이 더 안정적인 경우가 많습니다. 클라이언트 렌더링도 사용할 수 있습니다. 핵심은 프레임워크가 일반적으로 SEO에 적합하다는 평가가 아니라 특정 경로가 크롤러의 실제 조건에서 작동하는지입니다.
크롤링, 렌더링, 색인 생성 순서를 확인합니다
Google은 JavaScript 페이지를 처리하는 주요 단계를 크롤링, 렌더링, 색인 생성으로 설명합니다. 크롤링 중 Googlebot은 허용된 URL을 가져와 응답을 처리합니다. 초기 HTML에서 링크를 발견할 수 있습니다. Google의 웹 렌더링 서비스는 화면 인터페이스 없는 Chromium 환경에서 JavaScript를 실행합니다. 생성된 HTML은 콘텐츠와 추가 링크를 후속 처리에 제공합니다.
렌더링 대기열에 대해 고정된 대기 시간이 공개되어 있지는 않습니다. JavaScript 콘텐츠가 항상 즉시 나타난다거나 반드시 일정한 일수만큼 기다린다고 약속하지 않습니다. Google은 색인 지시문이 처리를 바꾸지 않는 한 적합한 200 페이지를 JavaScript 유무와 관계없이 렌더링 대기열에 넣는다고 설명합니다. 오류나 차단된 리소스에 따라 이후 결과가 달라질 수 있습니다.
렌더링과 색인 생성은 별개의 결과입니다. 정상적으로 렌더링되어도 중복, 품질 또는 다른 요인 때문에 색인에 선택되지 않을 수 있습니다. 특정 문구가 검색되지 않는다고 Google이 JavaScript를 실행하지 못했다고 단정할 수는 없습니다. 검사 증거가 실제로 무엇을 보여 주는지 확인합니다.
모든 제외를 렌더링 결함으로 보기 전에 기술 SEO 기초 가이드로 접근, 표준 URL, 상태 코드를 점검합니다. 여기서 설명하는 처리 모델의 주요 근거는 Google JavaScript SEO 문서입니다.
중요한 경로의 세 가지 모습을 비교합니다
상품 상세 페이지나 충분한 설명이 있는 가이드처럼 콘텐츠 누락이 중요한 경로를 고릅니다. 예상 제목, 고유 본문, 주요 링크, 표준 URL, 색인 지시문을 적습니다. 그다음 화면 인상에 의존하지 말고 원래 응답과 렌더링 결과를 비교합니다.
먼저 서버 HTML과 헤더를 가져옵니다. 다음으로 새 브라우저 세션에서 URL을 직접 열고 DOM, 네트워크 실패, 콘솔 예외를 확인합니다. 마지막으로 Search Console URL 검사를 사용하고 필요한 경우 실시간 테스트를 합니다. 저장된 색인 보고서와 현재 테스트는 서로 다른 질문에 답하며 다른 버전을 반영할 수 있습니다.
각 증거의 범위는 다음과 같습니다.
| 증거 | 확인할 수 있는 내용 | 입증하지 못하는 내용 |
|---|---|---|
| HTTP 응답과 소스 HTML | 초기 콘텐츠, 헤더, 상태 | 전체 렌더링 DOM |
| 로컬 DOM과 네트워크 기록 | 해당 세션의 실행 동작 | Google이 이전에 색인한 내용 |
| URL 검사의 색인 정보 | 저장된 크롤링 및 색인 정보 | 새 배포 이후의 현재 동작 |
| 실시간 검사 또는 리치 결과 테스트 | 현재 렌더링과 지원되는 검사 | 색인이나 검색 순위 보장 |
렌더링 HTML에서 실제 문구와 링크 목적지를 찾습니다. 화면 캡처는 레이아웃 조사에 도움이 되지만 모든 메타데이터와 링크 의미를 보여 주지는 않습니다. 리치 결과 테스트에 성공해도 페이지의 핵심 설명이 존재하는지 별도로 확인해야 합니다.
배포 버전과 검사 시간을 기록합니다. 서버는 새 마크업을 반환하지만 이전 번들이 캐시되어 있다면 배포 전환 중에만 문제가 생길 수 있습니다. 같은 경로를 직접 열고 클라이언트 탐색으로도 이동합니다. 홈페이지에서 이동할 수 있다는 사실이 깊은 URL의 독립적인 작동을 입증하지는 않습니다.
상호작용, 저장 상태, 인증에 대한 의존성을 없앱니다
Googlebot은 로그인한 구매자처럼 화면을 클릭하며 진행하지 않습니다. 공개 콘텐츠를 가져오는 데 클릭, 스크롤 이벤트, 특정 localStorage 값이 필요해서는 안 됩니다. 펼침 버튼을 눌러야 요청하는 상품 설명은 이미 DOM에 있으면서 작은 인터페이스로 표시하는 텍스트와 다릅니다.
누락된 구역의 데이터 요청을 살펴봅니다. 세션 쿠키, 비공개 인증 정보, 다른 경로의 사전 방문 없이 성공하는지 확인합니다. 캐시가 채워진 브라우저는 초기화 실패를 숨길 수 있습니다. 공개 페이지 렌더링에 필요한 API와 스크립트는 해당 조건에서 접근 가능해야 합니다.
모든 브라우저 API가 렌더링 서비스에서 똑같이 동작한다고 가정하지 않습니다. 선택 기능은 지원 여부를 확인하고 유용한 대안을 제공합니다. 핵심 텍스트를 위치 권한 같은 허가와 분리합니다. 언어나 지역 버전은 클라이언트 설정을 저장해야만 존재하는 상태가 아니라 안정적인 직접 URL을 가져야 합니다.
중요한 콘텐츠에서 무관한 의존성도 제거합니다. 분석 요청 실패 때문에 상품 정보가 표시되지 않는다면 독립된 작업을 불필요하게 연결한 것입니다. 핵심 콘텐츠를 독립적으로 렌더링하고 선택적 연동은 별도로 처리합니다. 방문자와 크롤러 모두에게 더 견고한 페이지가 됩니다.
정해진 클릭 경로 없이 링크와 경로가 작동하게 합니다
탐색에는 사용할 수 있는 href를 가진 앵커 요소를 사용합니다. onClick 버튼은 작업 실행에 적합하지만 다른 문서로 연결되는 발견 가능한 링크를 대신하지는 않습니다. JavaScript로 일반 링크를 개선하더라도 목적지는 유지합니다.
다음 페이지 나누기 링크는 화면이 빠른 전환을 위해 이벤트를 가로채더라도 실제 URL로 남습니다.
<nav aria-label="Catalog pages">
<a href="/catalog/?page=2">Next catalog page</a>
</nav>목적지도 직접 요청했을 때 작동해야 합니다. 서버와 라우터가 깊은 URL에 알맞은 콘텐츠와 상태를 반환하도록 구성합니다. 일부 구조에는 공통 앱 셸이 필요하지만 모든 잘못된 경로까지 성공한 페이지처럼 만들면 안 됩니다.
의미 있는 URL 사이의 클라이언트 라우팅에는 History API를 사용합니다. 별도의 색인 가능한 문서를 #/products 같은 프래그먼트로 식별하지 않습니다. 프래그먼트는 문서 안의 위치를 나타낼 수 있지만 Google이 설명한 문서 URL 전략을 안정적으로 대체하지 못합니다.
없는 상품, 만료된 경로, 잘못된 매개변수를 테스트합니다. 200 응답 안의 클라이언트 오류 메시지는 소프트 404가 될 수 있습니다. 가능하면 적절한 서버 상태를 반환합니다. Google은 클라이언트 전용 앱의 대안을 설명하지만 대안이 서버 응답을 무시하는 이유가 되어서는 안 됩니다.
초기 응답과 렌더링 후 메타데이터를 일치시킵니다
색인할 각 경로에 설명적인 제목, 관련 있는 설명, 일관된 표준 URL을 제공합니다. 서버 HTML에 넣으면 의존성이 줄고 검사가 쉬워집니다. JavaScript로 메타데이터를 설정할 수 있지만 기존 canonical을 나중에 다른 주소로 바꾸면 신호가 충돌합니다.
다음 상품 head 예제에는 하나의 canonical과 콘텐츠에 맞는 메타데이터가 있습니다.
<title>Oak desk specifications and dimensions</title>
<meta name="description" content="Dimensions, materials and assembly information for the oak desk.">
<link rel="canonical" href="https://example.com/products/oak-desk/">메타데이터 라이브러리는 의도한 요소를 갱신해야 하며 canonical이나 충돌하는 robots 태그를 계속 추가해서는 안 됩니다. 원본 템플릿뿐 아니라 경로 전환 후 최종 DOM도 확인합니다. 이전 경로의 상태가 남으면 다음 화면에 잘못된 제목이나 canonical이 적용될 수 있습니다.
noindex는 특히 주의합니다. 초기 HTML에 색인 금지가 있으면 Google이 렌더링을 생략할 수 있습니다. 응답에 noindex를 넣은 뒤 JavaScript가 제거하기를 기대하는 방식은 안정적이지 않습니다. 공개 페이지를 색인하려면 첫 응답부터 의도가 일관되어야 합니다.
구조화된 데이터도 JavaScript로 생성할 수 있지만 화면에 보이는 정확한 콘텐츠를 설명해야 합니다. 렌더링 결과에 존재하는지, 페이지와 일치하는지 확인합니다. 올바른 마크업만으로 로드하지 못한 상품 설명이나 가격을 보완할 수 없고 리치 결과도 보장하지 않습니다.
문서를 숨기지 않고 리소스를 지연 로드합니다
화면 밖 이미지를 지연 로드하면 불필요한 전송을 줄일 수 있습니다. 반면 스크롤 이벤트 뒤에만 본문을 가져오면 색인에 사용하는 결과에 글이 나타나지 않을 수 있습니다. 리소스 최적화와 페이지를 정의하는 콘텐츠를 숨기는 일을 구분합니다.
Google은 관련 콘텐츠가 뷰포트에 보일 때 로드하고 사용자 동작 의존성을 피하라고 안내합니다. 이미지는 지원되는 브라우저 로딩 기능이나 검증한 가시성 기반 방식을 사용합니다. 요소가 렌더링될 때 실제 이미지 URL을 사용할 수 있어야 합니다. 늦게 도착해도 주변 내용을 밀지 않도록 공간을 확보합니다.
무한 스크롤에는 접근 가능한 링크와 의미 있는 콘텐츠 묶음을 제공하는 페이지별 URL을 마련합니다. 방문자가 연속 피드를 선호해도 개별 구간에는 가져올 수 있는 주소와 발견 경로가 필요합니다. 뒤쪽 페이지를 직접 테스트합니다. 내 브라우저에서 여러 번 스크롤했다고 검색엔진의 전체 접근이 증명되지는 않습니다.
모든 이미지 컴포넌트의 기본값이 같다는 이유로 첫 화면의 중요한 LCP 이미지까지 지연 로드하지 않습니다. 전달 방식은 검색과 성능 모두에 영향을 줍니다. 먼저 콘텐츠가 안정적으로 도착하는지 확인하고 그다음 보조 리소스가 언제 대역폭을 사용할지 조정합니다.
제거할 수 있는 의존성을 기준으로 렌더링을 선택합니다
정적 생성은 요청 전에 HTML을 만듭니다. 서버 렌더링은 요청 처리 중에 만듭니다. 두 방식 모두 중요한 텍스트와 링크를 응답에 포함할 수 있습니다. 클라이언트 렌더링은 스크립트와 보통 데이터까지 로드한 다음 브라우저에서 콘텐츠를 생성합니다. 하이드레이션은 이미 존재하는 HTML에 상호작용을 추가합니다.
애플리케이션 안에서 이런 방식은 함께 사용할 수 있습니다. 공개 문서는 정적이고 개인 계정 화면은 동적이며 작은 필터는 상호작용 요소일 수 있습니다. Next.js 성능 가이드는 서버와 클라이언트 컴포넌트 경계가 이런 선택과 어떻게 연결되는지 설명합니다.
서버 렌더링이 성능을 보장하지는 않습니다. 느린 데이터 의존성은 전체 응답을 늦추고 큰 클라이언트 번들은 텍스트가 나온 후에도 하이드레이션 비용을 키울 수 있습니다. 스트리밍으로 유용한 부분을 먼저 보낼 수 있지만 핵심 내용이 느린 의존성을 계속 기다리는지 확인합니다.
하이드레이션은 초기 콘텐츠를 유지해야 하며 모순되는 로딩 화면으로 교체해서는 안 됩니다. 서버와 클라이언트 출력의 불일치는 오류와 예상 밖 변경을 일으킬 수 있습니다. 스크립트 로딩 중과 이후를 모두 시험하며 느린 요청과 실패한 요청도 포함합니다.
동적 렌더링은 크롤러를 감지해 별도로 렌더링한 버전을 제공합니다. Google은 이를 장기 권장 사항이 아니라 우회 방법으로 설명합니다. 인프라가 늘고 출력의 동등성을 유지할 책임도 추가됩니다. 가능하면 일관된 렌더링 구조를 선택합니다. 최적화한다는 이유로 크롤러에게 실질적으로 다른 내용을 보여 주지 않습니다.
렌더링 실패를 성능 증거와 연결합니다
큰 JavaScript 번들은 다운로드, 파싱, 실행 작업을 늘릴 수 있습니다. 사용자에게 콘텐츠가 늦게 보이고 렌더링 의존성도 복잡해질 수 있습니다. 그러나 낮은 성능 점수만으로 Google의 콘텐츠 누락을 입증할 수 없으며 높은 점수로 색인 가능성을 확정할 수도 없습니다.
문서, 스크립트, API 요청, DOM 갱신, 표시라는 실제 경로를 추적합니다. 핵심 콘텐츠가 전체 사슬에 의존하면 어느 단계를 서버로 옮기거나 없앨 수 있는지 결정합니다. 콘텐츠가 나타난 뒤 작업이 상호작용을 막는다면 JavaScript 실행 시간 가이드가 적절한 다음 조사입니다.
성능 증거에는 PageSpeed 분석 도구를, 검색 렌더링 증거에는 Google 검사 도구를 사용합니다. 문제 기록에서도 두 결과를 분리합니다. “실시간 렌더링 HTML에 상품 제목이 없다”는 조치 가능한 설명입니다. “JavaScript가 SEO에 나쁘다”는 수정 방향을 정하기에 너무 넓습니다.
템플릿 수준에서 수정 결과를 확인합니다
변경 후 실패했던 정확한 경로와 같은 템플릿의 다른 경로를 다시 테스트합니다. 직접 여는 깊은 링크, 누락 리소스, 모바일 화면, 클라이언트 탐색을 포함합니다. 겉모습만 정상인지 보지 말고 핵심 콘텐츠, 링크, 메타데이터, 상태를 확인합니다.
변경한 JavaScript와 CSS는 콘텐츠 지문을 포함한 파일명을 사용해 새 코드에 별도 URL을 부여합니다. Google은 렌더링 서비스가 리소스를 적극적으로 캐시할 수 있다고 설명합니다. 버전이 구분된 자산은 결과를 만든 배포를 찾는 데도 도움이 됩니다. 그렇다고 일관된 배포 및 캐시 전략이 불필요해지는 것은 아닙니다.
무엇을 고쳤고 증거가 어디까지 설명하는지 기록합니다. 실시간 렌더링 성공은 해당 테스트에서 콘텐츠를 사용할 수 있었다는 뜻이며 색인과 순위는 별도로 관찰해야 합니다. 실패했던 시나리오를 기술 SEO 절차의 배포 검사에 추가해 다음 라우팅이나 렌더링 변경이 제거한 의존성을 다시 만들지 않게 합니다.