검색 엔진 크롤링과 자바스크립트 렌더링 정리

2025. 9. 8. 14:25·FrontEnd/web

"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 검색엔진 공식문서

참고 :  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) 라는 시스템을 따로 두고 있다.

흐름만 다시 정리하면 이렇다.

  1. 먼저 HTML을 기준으로 1차 크롤링과 색인을 진행한다.
  2. 자바스크립트 실행이 필요한 페이지는 렌더링 대기열(Rendering Queue)에 들어간다.
  3. WRS가 실제로 자바스크립트를 실행해서 최종 DOM을 만든다.
  4. 그 결과를 다시 색인에 반영한다.
  5. 이 과정에서 새롭게 발견된 링크는 다시 크롤링 대기열로 돌아간다.

여기서 중요한 포인트 몇 가지

  • 렌더링 대기열에 들어가는 순간,
    바로 처리된다는 보장은 없다.
    • 우선순위, 리소스 상황에 따라 몇 초, 몇 분, 심하면 더 오래 걸릴 수 있다.
  • 메타 태그로 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
'FrontEnd/web' 카테고리의 다른 글
  • [실무 기록] Chrome Inspect에서 Pending authentication만 뜨고 안드로이드 디버깅이 안 될 때
  • [실무 기록] 웹뷰 브릿지, 이거 누가 책임져야 하지?
  • 브라우저 동작 원리 - 화면이 그려지기까지
  • 동기식(Synchronous) vs 비동기식(Asynchronous)
프론트엔드 개발자 jbeat
프론트엔드 개발자 jbeat
프론트엔드 개발자 블로그인데 일상도 쪼그으믐
  • 프론트엔드 개발자 jbeat
    jbeat 님의 블로그
    프론트엔드 개발자 jbeat
  • 전체
    오늘
    어제
    • 분류 전체보기 (44)
      • FrontEnd (43)
        • TypeScript (6)
        • JavaScript (18)
        • Next.js (3)
        • React (1)
        • Testing (2)
        • Third Party (1)
        • web (10)
        • Tooling (1)
        • coding test (0)
        • A.I (1)
      • 일상 (1)
        • wedding (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • 태그

    pick
    omit
    이터러블
    CrossOrigin
    javascript
    Android
    preconnect
    타입스크립트
    TypeScript
    playwright
    yjs
    코테
    Utility
    주니어
    Next.js
    컬렉션
    CRDT
    WebSocket
    배열
    고차함수
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
프론트엔드 개발자 jbeat
검색 엔진 크롤링과 자바스크립트 렌더링 정리
상단으로

티스토리툴바