구조·마크업 · 공식 문서
리액트 SPA SEO, 검색에 안 나올 때 점검 순서
첫 HTML과 렌더링된 HTML에 본문이 있는지부터 보고, # URL·링크, 오류 페이지 상태 코드와 메타 태그, 리소스 차단 순으로 10가지를 점검합니다. SPA는 없는 페이지도 200으로 응답하기 쉬워 오류 페이지가 색인될 수 있다고 구글이 적었습니다.
SPA는 첫 HTML 하나를 받은 뒤 자바스크립트가 화면을 바꾸는 구조입니다. 사람에게는 빠르게 보이지만, 크롤러는 화면이 아니라 URL과 HTML 단위로 읽습니다.
그래서 SPA가 검색에 안 나오는 원인은 대개 크롤러가 받은 HTML·URL·상태 코드에 있습니다. 앞에서부터 차례로 보면 원인이 좁혀집니다.
발견 01
SPA 점검은 4묶음 10가지이고, 첫 HTML부터 봅니다
| 순서 | 묶음 | 확인할 것 | 확인 방법 | 공식 문서 원문 |
|---|---|---|---|---|
| 1 | HTML | 첫 HTML에 본문이 있는지 | view-source: 로 열어 본문 문장을 찾습니다. <div id="root"> 같은 빈 틀만 있으면 앱 셸 구조입니다. | Some JavaScript sites may use the app shell model where the initial HTML does not contain the actual content and Google needs to execute JavaScript before being able to see the actual page content that JavaScript generates.앱 셸 방식 사이트는 첫 HTML에 실제 콘텐츠가 없어, 구글이 자바스크립트를 실행해야 콘텐츠를 볼 수 있다. |
| 2 | HTML | 렌더링된 HTML에 본문이 있는지 | 서치 콘솔 URL 검사나 리치 결과 테스트로 렌더링된 HTML과 자바스크립트 콘솔 오류를 봅니다. | To test how Google crawls and renders a URL, use the Rich Results Test or the URL Inspection Tool in Search Console. You can see loaded resources, JavaScript console output and exceptions, rendered DOM, and more information.구글이 URL을 크롤링하고 렌더링하는 방식은 리치 결과 테스트나 서치 콘솔 URL 검사 도구로 시험한다. 불러온 리소스, 자바스크립트 콘솔 출력과 예외, 렌더링된 DOM 등을 볼 수 있다. |
| 3 | URL·링크 | 화면마다 # 없는 고유 URL이 있는지 | 메뉴를 눌렀을 때 /#/products 처럼 # 뒤만 바뀌면 History API 라우팅으로 바꿉니다. | The AJAX-crawling scheme has been deprecated since 2015, so you can't rely on URL fragments to work with Googlebot.AJAX 크롤링 방식은 2015년부터 지원이 중단됐으므로, Googlebot 에서 # 조각 URL이 동작한다고 기대할 수 없다. |
| 4 | URL·링크 | 메뉴·목록 링크가 <a href> 인지 | 버튼의 onclick 으로만 이동하는 링크가 없는지 렌더링된 HTML에서 찾습니다. | Google can only discover your links if they are <a> HTML elements with an href attribute.구글은 href 속성이 있는 <a> HTML 요소만 링크로 발견할 수 있다. |
| 5 | 메타·상태 | 없는 URL이 200으로 응답하지 않는지 | 없는 상품 번호 URL을 열어 상태 코드를 봅니다. 200이면 404 URL로 보내거나 noindex 를 넣습니다. | When a SPA is using client-side JavaScript to handle errors they often report a 200 HTTP status code instead of the appropriate status code. This can lead to error pages being indexed and possibly shown in search results.SPA가 클라이언트 자바스크립트로 오류를 처리하면 알맞은 상태 코드 대신 200을 보내는 경우가 많다. 그러면 오류 페이지가 색인되고 검색 결과에 나올 수 있다. |
| 6 | 메타·상태 | <title>·메타 설명·캐노니컬이 화면마다 바뀌는지 | 렌더링된 HTML에서 화면마다 제목이 다른지, 캐노니컬이 하나뿐이고 첫 HTML 값과 같은지 봅니다. | The best way to set the canonical URL is to use HTML, but if you have to use JavaScript, make sure that you always set the canonical URL to the same value as the original HTML. Conflicting or multiple rel="canonical" link tags may lead to unexpected results.캐노니컬 URL은 HTML로 정하는 것이 가장 좋다. 자바스크립트를 써야 한다면 늘 원래 HTML과 같은 값으로 정한다. 충돌하거나 여러 개인 캐노니컬 태그는 예상하지 못한 결과를 낼 수 있다. |
| 7 | 메타·상태 | 첫 HTML의 noindex 를 자바스크립트로 지우지 않는지 | 색인할 화면의 첫 HTML에 noindex 가 있으면 첫 HTML에서 뺍니다. | When Google encounters the noindex tag, it may skip rendering and JavaScript execution, which means using JavaScript to change or remove the robots meta tag from noindex may not work as expected.noindex 태그를 만나면 렌더링과 자바스크립트 실행을 건너뛸 수 있다. 그래서 자바스크립트로 noindex 를 바꾸거나 지우는 방식은 기대대로 동작하지 않을 수 있다. |
| 8 | 리소스 | robots.txt 가 자바스크립트·CSS·API 경로를 차단하지 않는지 | 번들 파일 경로와 데이터를 불러오는 API 경로가 Disallow 에 걸리는지 봅니다. | Google Search won't render JavaScript from blocked files or on blocked pages.차단된 파일이나 차단된 페이지의 자바스크립트는 렌더링하지 않는다. |
| 9 | 리소스 | 저장소·쿠키·권한이 있어야 본문이 나오지 않는지 | 시크릿 창에서 처음 연 것처럼 저장소와 쿠키 없이도 본문이 나오는지 봅니다. | Local Storage and Session Storage data are cleared across page loads. HTTP Cookies are cleared across page loads.로컬 저장소와 세션 저장소 데이터는 페이지를 불러올 때마다 지워진다. HTTP 쿠키도 페이지를 불러올 때마다 지워진다. |
| 10 | 리소스 | 본문 데이터를 HTTP로 불러오는지 | 본문을 WebSocket 으로만 받는 화면이 있으면 HTTP 요청으로도 받을 수 있게 합니다. | It does not support other types of connections, such as WebSockets or WebRTC connections.Googlebot 은 WebSocket 이나 WebRTC 같은 다른 연결 방식을 지원하지 않는다. |
첫 HTML이 비어 있어도 구글은 렌더링해서 읽지만, 렌더링 대기열을 거치고 렌더링하지 않는 크롤러는 빈 페이지로 봅니다. 그래서 두 번째 점검에서 렌더링 결과를 따로 확인합니다.
렌더링 단계에서 구글과 네이버가 하는 일은 「자바스크립트 SEO」 편에 자세히 적었습니다.
발견 02
SPA는 없는 페이지도 200으로 응답하기 쉬워, 오류 페이지가 색인될 수 있습니다
When a SPA is using client-side JavaScript to handle errors they often report a 200 HTTP status code instead of the appropriate status code. This can lead to error pages being indexed and possibly shown in search results.
SPA가 클라이언트 자바스크립트로 오류를 처리하면 알맞은 상태 코드 대신 200을 보내는 경우가 많다. 그러면 오류 페이지가 색인되고 검색 결과에 나올 수 있다.
| 방법 | 공식 문서 원문 |
|---|---|
| 404 URL로 보내기 | Use a JavaScript redirect to a URL for which the server responds with a 404 HTTP status code (for example /not-found).서버가 404 상태 코드로 응답하는 URL(예: /not-found)로 자바스크립트 리디렉션을 한다. |
| 오류 화면에 noindex 넣기 | Add a <meta name="robots" content="noindex"> to error pages using JavaScript.오류 페이지에 자바스크립트로 noindex 로봇 메타 태그를 넣는다. |
서버는 어떤 URL이든 같은 첫 HTML을 200으로 돌려주고, 「상품이 없습니다」는 자바스크립트가 그립니다. 그러면 크롤러는 오류 화면을 정상 페이지로 받습니다.
noindex 는 오류 화면에만 자바스크립트로 넣습니다. 반대로 색인할 화면의 첫 HTML에 noindex 를 두고 지우면, 구글이 렌더링을 건너뛸 수 있습니다. soft 404 전반은 「soft 404 뜻」 편에 적었습니다.
발견 03
SPA는 화면마다 # 없는 고유 URL이 있어야 구글·네이버가 화면별로 읽습니다
| 검색엔진 | 원문 |
|---|---|
| 구글 | The AJAX-crawling scheme has been deprecated since 2015, so you can't rely on URL fragments to work with Googlebot.AJAX 크롤링 방식은 2015년부터 지원이 중단됐으므로, Googlebot 에서 # 조각 URL이 동작한다고 기대할 수 없다. |
| 네이버 | 네이버 검색로봇은 수집 대상 URL 을 해석하는 과정에서 fragment 부분을 제거합니다. |
네이버는 수집할 URL에서 # 뒤를 지우므로 /#/products 와 /#/services 가 같은 URL 하나로 수집됩니다. 화면마다 /products 같은 고유 URL로 바꿉니다.
링크도 href 가 있는 <a> 요소여야 구글이 발견합니다. 버튼 클릭으로만 이동하는 메뉴는 크롤러에게는 링크가 아닙니다.
발견 04
같은 SPA라도 B2B·B2C·B2G 는 먼저 걸리는 점검이 다릅니다
예시 ① 요금·기능 페이지까지 앱 안에 둔 B2B 서비스
공개 페이지도 앱 라우터 안에 있어 첫 HTML이 비어 있고, 제목이 모든 화면에서 같았습니다. 첫 HTML 점검과 제목·캐노니컬 점검에서 함께 걸리는 경우입니다.
공개 페이지만 서버 측 렌더링이나 정적 렌더링으로 떼어 내는 방법은 「SSR CSR SSG SEO 차이」 편에 적었습니다.
예시 ② 품절 상품 URL이 그대로 열리는 쇼핑몰(B2C)
삭제된 상품 URL도 200으로 응답하고 「없는 상품」 화면을 그렸습니다. 서치 콘솔에 soft 404 가 쌓이는 경우입니다.
삭제된 상품은 서버가 404로 응답하는 URL로 보내고, 품절이지만 남길 상품은 본문을 그대로 둡니다.
예시 ③ # 로 메뉴를 바꾸는 공공기관 안내 누리집(B2G)
메뉴마다 /#/notice, /#/guide 처럼 # 뒤만 바뀌었습니다. 네이버에는 첫 화면 하나만 수집됩니다.
유지보수 과업에 「화면별 고유 URL과 <a href> 메뉴」를 검수 항목으로 넣습니다.
그럼 오늘 무엇부터 확인하나요?
- 검색에 안 나오는 URL 하나를 골라 view-source: 로 열고 본문 문장을 찾습니다.
- 같은 URL을 서치 콘솔 URL 검사로 테스트해 렌더링된 HTML과 콘솔 오류를 봅니다.
- 메뉴를 눌러 URL이 # 없이 바뀌는지, 링크가 <a href> 인지 봅니다.
- 없는 URL을 하나 만들어 열고 상태 코드가 404인지 확인합니다.
- 나머지 점검은 위 표 순서대로 보고, 고친 뒤 URL 검사로 다시 테스트합니다.
조사 방법
- Google Search Central 「Understand the JavaScript SEO basics」 (문서 수정일 2026-03-04) · 최종 확인일 2026-10-25 · https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics
- Google Search Central 「Fix Search-related JavaScript problems」 (문서 수정일 2025-12-18) · 최종 확인일 2026-10-25 · https://developers.google.com/search/docs/crawling-indexing/javascript/fix-search-javascript
- 네이버 서치어드바이저 「자바스크립트 검색 최적화」 · 최종 확인일 2026-10-25 · https://searchadvisor.naver.com/guide/seo-advanced-javascript
- 점검 10가지는 위 문서들이 SPA·자바스크립트 사이트에 대해 확인하라고 적은 일을 점검 순서로 묶은 것입니다. 묶는 방식과 「확인 방법」 칸은 편집 판단입니다.
- 예시 ①②③은 이해를 돕기 위해 만든 가상 상황이며, 실제 기업·기관의 사례가 아닙니다.
- 원문은 영어판(hl=en)이고, 도구·보고서 이름은 같은 문서 한국어판(hl=ko) 표기를 따랐습니다.