"SPA + CSR 시대에, 검색 엔진이 자바스크립트 페이지를 어떻게 보고 있는지 정리해보자"
프론트 개발하다 보면 한 번쯤 이런 고민이 온다.
- 우리 서비스는 SPA + CSR인데, 검색 엔진이 제대로 가져가고 있을까?
- 구글은 자바스크립트를 돌려 준다는데, 그럼 SEO는 그냥 믿고 맡겨도 되는 걸까?
- SSR, SSG, 동적 렌더링 이런 키워드들 사이에서 뭘 골라야 하는지 막막할 때가 있다.
이 글은 구글 공식 문서 + 직접 테스트해 본 경험을 바탕으로,
- 검색 엔진 크롤링/색인 흐름
- 자바스크립트 렌더링(WRS, 렌더링 대기열)
- 실무에서 SSR/사전 렌더링/동적 렌더링을 어떻게 선택할지
이 세 가지를 한 번에 정리해 둔 기록이다.
1. 결론 먼저
먼저 결론부터 보자
- 대부분의 검색 엔진은 여전히 초기 HTML 기준으로 페이지를 본다.
- 구글/빙은 자바스크립트를 실행해서 렌더링된 DOM 기준으로 색인할 수 있다.
- 그렇다고 해서 "CSR만 써도 다 해결" 되는 건 아니다.
- 실무에서 가장 안전한 전략은 여전히
- SSR(서버사이드 렌더링)
- 사전 렌더링(Static Generation)
- 필요 시 동적 렌더링(Dynamic Rendering) 을 섞어서, 초기 HTML에 의미 있는 콘텐츠를 최대한 넣어두는 것이다.
한 줄로 요약하면
"구글이 자바스크립트를 잘 돌려 주는 건 맞지만,
그래도 SSR/사전 렌더링을 같이 가져가는 쪽이 SEO와 UX 모두에서 더 안전하다."
2. 구글 검색 동작 순서 (크롤링 → 색인 → 게재)
먼저 전체 흐름부터 한 번 잡고 가면, 뒤에 나오는 자바스크립트 처리도 이해하기가 쉽다.
2-1. 공식 영상 참고
구글에서 직접 설명하는 영상이 있다.
이 글 쓰기 전에 먼저 이거부터 보고 정리했다.
참고: Google 검색엔진 공식문서
2-2. 전체 흐름 다이어그램
영상/문서에 나오는 구조도를 그대로 가져오면 이런 느낌이다.

왼쪽에서 오른쪽으로 흐름을 따라가 보면,
- Crawling Queue(크롤링 대기열)
- Crawler(크롤러)
- Processing(처리)
- Index(색인)
- 그리고 중간에 Rendering Queue(렌더링 대기열), Renderer(WRS)
이렇게 나뉘어 있는 걸 볼 수 있다.
아래부터는 이 그림 기준으로, 단계를 나눠서 정리해 본다.
2-3. 1단계: 크롤링 (Crawling)
가장 왼쪽 단계
- Googlebot이 URL을 방문한다.
- HTML, CSS, JS, 이미지 등 리소스를 다운로드한다.
- robots.txt를 확인해서 허용된 리소스만 가져온다.
- 페이지 안에서 발견한 링크들을 크롤링 대기열에 쌓는다.
여기까지는 단순히 "페이지와 링크를 모으는 작업"이라고 생각하면 편하다.
2-4. 2단계: 색인 생성 (Indexing)
그다음은 색인 단계
- 받아온 HTML을 분석해서 텍스트, 메타데이터, 이미지 정보를 추출한다.
- 추출한 정보를 구글의 색인(Index)에 저장한다.
- 제목, 본문, 메타 태그, 구조화 데이터(JSON-LD) 등이 이때 같이 고려된다.
이 단계가 끝나야, 비로소 검색 결과에 등장할 수 있는 "후보 문서"가 된다.
3. 검색 결과 게재 (Serving Search Results)
크롤링과 색인까지 끝났다고 해서 바로 끝이 아니다.
사용자가 검색어를 입력했을 때, 어떤 문서를 어떤 순서로 보여줄지를 정하는 단계가 한 번 더 있다. 그게 바로 "검색 결과 게재(Serving)" 단계다.
3-1. 사용자의 검색 의도 파악
사용자가 검색창에 키워드를 입력하면, 구글은 단순히 단어만 보는 게 아니다.
- 검색어 자체 (키워드, 철자, 유사어)
- 언어와 지역 (한국어 사용자인지, 어느 국가/도시인지)
- 기기 종류 (모바일/데스크탑)
- 로그인 상태, 과거 검색 기록 등 개인화 신호
이런 것들을 전부 고려해서, "이 사람이 지금 이 검색어로 무엇을 알고 싶어 하는지"를 먼저 추측한다.
예를 들어
- 자바스크립트 크롤링 → 기술 문서, 개발 블로그, 공식 문서 위주
- 카카오프렌즈 이모티콘 → 스토어/상점, 이미지 중심 결과
같은 단어여도, 의도와 맥락에 따라 보여주는 결과 구성이 달라진다.
3-2. 후보 문서 랭킹(순위 결정)
검색 의도를 어느 정도 파악했으면, 이제 색인된 문서들 중에서 "후보들을 뽑고, 순위를 매기는 단계"로 들어간다.
대표적으로 고려되는 것들
- 관련성(Relevance)
- 검색어와 문서 내용이 얼마나 잘 맞는지
- 단순 키워드 매칭뿐 아니라, 의미(시맨틱) 기반 유사성까지 같이 본다.
- 콘텐츠 품질과 신뢰도
- 글이 얼마나 유용한지, 내용이 충실한지
- 사이트 평판, 외부 링크, 작성자/사이트의 신뢰도 같은 신호
- 사용자 경험(UX)
- 페이지 속도, 모바일 최적화, HTTPS 사용 여부
- 화면을 덮어 버리는 팝업, 과도한 광고 같은 방해 요소
- 신선도(Freshness)
- 뉴스/이슈성 키워드는 최신 문서에 가산점
이런 요소들을 종합해서 랭킹 알고리즘이 점수를 매기고,
그 결과가 우리가 실제로 보게 되는 검색 결과 순서다.
3-3. 검색 결과 페이지 구성
마지막으로, 점수가 매겨진 문서들을 가지고 검색 결과 페이지(SERP)를 구성한다.
여기에는 보통 이런 것들이 섞여 있다.
- 일반 웹 문서 결과 (파란 링크 + 설명 텍스트)
- 이미지, 동영상, 뉴스, 지도 같은 수직 검색(vertical) 결과
- 풍부한 결과
- FAQ, 별점, 썸네일, 사이트 링크 같은 리치 리절트(Rich Results)
- 특정 질문에 대한 요약 박스(Featured Snippet) 등
- 광고(Ads)
- 자연 검색 결과와 같은 화면에 보이지만,
- 별도의 광고 경매 시스템으로 순위가 결정되는 유료 영역
정리하면, Serving 단계는 이렇게 정의할 수 있다.
이미 색인된 문서들 중에서,
사용자의 검색 의도에 가장 잘 맞는 것들을 고르고,
어떤 모양과 순서로 보여줄지 결정하는 단계.
앞의 크롤링/렌더링/색인이 "자료를 모으고 정리하는 과정"이라면,
Serving은 그 자료를 "사용자가 원하는 순간에, 원하는 형태로 꺼내서 보여주는 마지막 단계"라고 보면 된다.
4. 자바스크립트 기반 사이트에서 생기는 문제
이제 본론인 자바스크립트 얘기로 돌아가 보자.
SPA + CSR 구조에서는 보통 이렇게 된다.
- 초기 HTML에는 실제 콘텐츠가 거의 없다.
- div#app 하나랑 스크립트 태그만 있을 때도 있다.
- 자바스크립트가 실행되고 나서야 진짜 DOM이 만들어진다.
- 자바스크립트를 실행할 수 없는 봇은 "거의 빈 페이지"로 인식할 수 있다.
여기에 검색 엔진별 차이까지 얹힌다.
- 일부 검색 엔진은 아예 자바스크립트를 실행하지 못한다.
- 구글/빙은 자바스크립트를 실행할 수 있지만, 추가 단계(렌더링)를 거쳐야 한다.
- 이 렌더링 과정 때문에, HTML만 있는 페이지보다
- 크롤링/색인까지 더 오래 걸리거나
- 특정 페이지가 아예 누락되는 경우도 생길 수 있다.
그래서 현실적으로는 이렇게 받아들이는 편이 더 맞다.
"CSR = SEO 망한다"까지는 아니지만,
CSR만 믿고 아무 대책도 안 세우면
검색 엔진마다 결과가 들쭉날쭉해질 수 있다.
5. 구글의 자바스크립트 처리: 렌더링 대기열과 WRS
구글은 자바스크립트 페이지를 처리하기 위해 Web Rendering Service(WRS) 라는 시스템을 따로 두고 있다.
흐름만 다시 정리하면 이렇다.
- 먼저 HTML을 기준으로 1차 크롤링과 색인을 진행한다.
- 자바스크립트 실행이 필요한 페이지는 렌더링 대기열(Rendering Queue)에 들어간다.
- WRS가 실제로 자바스크립트를 실행해서 최종 DOM을 만든다.
- 그 결과를 다시 색인에 반영한다.
- 이 과정에서 새롭게 발견된 링크는 다시 크롤링 대기열로 돌아간다.
여기서 중요한 포인트 몇 가지
- 렌더링 대기열에 들어가는 순간,
바로 처리된다는 보장은 없다.- 우선순위, 리소스 상황에 따라 몇 초, 몇 분, 심하면 더 오래 걸릴 수 있다.
- 메타 태그로 noindex가 걸려 있는 페이지라면,
렌더링 자체를 건너뛸 수도 있다. - 구글 문서에서도, 자바스크립트가 필요한 페이지는
순수 HTML 페이지보다 크롤링/색인이 늦어질 수 있다고 직접 명시하고 있다.
즉, "구글이 JS 돌려 주니까 괜찮겠지"가 아니라,
"구글이 JS를 돌려주긴 하지만, 그조차도 리소스를 더 쓰고,
순수 HTML 페이지보다 느릴 수 있다"
라고 이해하는 쪽이 더 현실적이다.
6. 실무에서 쓸 수 있는 전략들
실제 서비스에 적용한다고 생각하고,
내가 정리해 둔 선택지들을 쭉 정리해본다.
6-1. 서버사이드 렌더링(SSR)
- 초기 HTML에 실제 콘텐츠를 넣어서 내려준다.
- 자바스크립트는 그 이후에 하이드레이션/인터랙션만 담당한다.
장점
- 자바스크립트를 실행하지 못하는 봇도 어느 정도 내용을 볼 수 있다.
- 사용자 입장에서도 첫 화면이 빨리 뜬다.
6-2. 사전 렌더링(Static Generation)
- 빌드 시점에 정적 HTML 파일을 미리 만들어 둔다.
- 배포 시에는 만들어 둔 파일을 그대로 서빙한다.
블로그, 문서, 마케팅 페이지처럼 자주 안 바뀌는 페이지는 이쪽이 잘 맞는다.
- 첫 로딩 속도
- 검색 엔진 친화도
두 가지를 같이 챙길 수 있다.
6-3. 동적 렌더링(Dynamic Rendering)
- 실제 사용자는 SPA/CSR 버전을 그대로 본다.
- 검색 엔진 봇(User-Agent 감지)에게는 미리 렌더링된 HTML 버전을 내려준다.
콘텐츠가 동일하거나 거의 유사하다면,
구글은 이 방식을 cloaking으로 보지 않는다고 문서에서 명시하고 있다.
다만 단점도 있다.
- 구현 난이도가 꽤 있다.
- 크롤링용 렌더링 서버를 따로 관리해야 할 수 있다.
그래서 대규모 서비스나 SEO가 매우 중요한 서비스가 아니라면,
SSR/SSG만으로도 충분한 경우가 많다.
6-4. 기본 SEO 설정들
JS 여부와 상관없이, 이런 것들은 항상 한 번씩 체크해 볼 만하다.
- robots.txt에서 HTML, CSS, JS, 이미지 접근을 막고 있지 않은지
- <title>, <meta name="description"> 같은 기본 메타 태그를 제대로 설정했는지
- 구조화 데이터(JSON-LD)로 검색엔진에 추가 정보를 주고 있는지
- SPA 라우팅을 History API 기준으로 안정적으로 처리하고 있는지
- 색인되면 안 되는 페이지에는 noindex를 적용했는지
7. 체크리스트
실제 프로젝트를 기준으로, 내가 스스로에게 던지는 질문들이다.
- 초기 HTML에 핵심 콘텐츠가 포함되어 있는가?
- 자바스크립트를 실행하지 못하는 봇도 페이지 내용을 어느 정도 볼 수 있는가?
- robots.txt에서 JS/CSS/이미지 리소스를 불필요하게 막고 있지는 않은가?
- Google Search Console의 URL 검사 도구로 실제 렌더링 결과를 확인해 봤는가?
- SSR, 사전 렌더링, 동적 렌더링 중 현재 서비스 특성에 가장 맞는 전략을 골랐는가?
- 불필요한 페이지, 테스트 페이지 등에 noindex를 적용해 두었는가?
8. 마무리 요약
마지막으로, 이 글 전체를 다시 한 번 요약해 보면
- 구글/빙은 자바스크립트를 실행해서 렌더링된 페이지를 색인할 수 있다.
- 하지만 모든 검색 엔진이 그 수준으로 JS를 처리하는 것은 아니다.
- 구글조차 자바스크립트 렌더링은 별도 단계(WRS, 렌더링 대기열)를 거치며,
순수 HTML 기반 페이지보다 느려질 수 있다. - 실무에서는 여전히
- SSR
- 사전 렌더링
- 적절한 SEO 설정 같은 것들을 섞어서, 초기 HTML에 의미 있는 콘텐츠를 넣어두는 구조가 가장 안전하다.
결국 이렇게 정리할 수 있을 것 같다.
"구글이 자바스크립트를 잘 돌려 준다고 해서,
아무것도 안 해도 된다는 뜻은 아니다.
오히려 그 위에 SSR/SSG/SEO 설정을 덧붙여서,
검색 엔진과 사용자 모두에게 친절한 구조를 만들어 주는 게 지금도 중요하다."
'FrontEnd > web' 카테고리의 다른 글
| [실무 기록] <link rel="stylesheet">로 CSS 불러오는데 간헐적으로 CORS 에러가 나던 이유 (해결: crossorigin 제거) (1) | 2026.01.13 |
|---|---|
| [실무 기록] Chrome Inspect에서 Pending authentication만 뜨고 안드로이드 디버깅이 안 될 때 (0) | 2026.01.12 |
| [실무 기록] 웹뷰 브릿지, 이거 누가 책임져야 하지? (0) | 2025.12.10 |
| 브라우저 동작 원리 - 화면이 그려지기까지 (0) | 2024.12.06 |
| 동기식(Synchronous) vs 비동기식(Asynchronous) (2) | 2024.12.06 |