귀하의 SPA가 검색되도록 돕기
Source: Dev.to
나는 내가 자랑스러워하는 무언가를 만들었다. 아무도 찾을 수 없었다.
제품을 만드는 것은 쉬운 부분이었다.
몇 달 동안 개발자 도구—실제 문제를 해결하는 진짜 제품—을 만들었다. 배포했고, 작동한다. 나는 진심으로 자랑스럽다.
그런 다음 내 사이트를 구글에 검색했다.
홈페이지는 겨우 나타났다. 다른 페이지는? 보이지 않는다. 내 문서 페이지, 템플릿 페이지, 가격 페이지—구글은 존재조차 몰랐다. 링크를 LinkedIn과 Twitter에 공유했을 때, 모든 페이지가 같은 일반 미리보기 카드만 보여줬다. Slack, Discord—같은 이야기다.
우리는 모두 “만들면 사람들이 올 것이다”라는 말을 들어봤다. 그리고 그게 작동하지 않는다는 걸 머리속으로는 알면서도, 어느 정도는 기대하게 된다. 뭔가 훌륭한 것을 만들고, 배포하고, 사람들이 네 천재성을 우연히 발견하기를 기다린다. 하지만 그들은 오지 않는다.
작업에 눈길을 끄는 것이 아무도 경고하지 않는 가장 어려운 문제다. 나에게는 그 근본 원인이 놀라울 정도로 단순했다.
모든 SPA 개발자가 겪는 문제
만약 당신이 React, Vue, Svelte 등으로 단일 페이지 애플리케이션을 만들었다면, 지금 이 순간에도 이 문제를 겪고 있을 것입니다. 인지하고 있든 아니든 말이죠.
- 당신의 앱은
index.html하나만 배포합니다.<script>태그 하나.<script>태그 하나. - 사이트의 모든 라우트(
/docs,/pricing,/about등)는 검색 엔진과 소셜 플랫폼에 정확히 같은 메타데이터를 제공합니다. - 당신은 10개의 페이지를 가지고 있습니다. Google은 하나만 보게 됩니다. LinkedIn은 하나만 보게 됩니다. Twitter는 하나만 보게 됩니다. Slack도 하나만 보게 됩니다.
- JavaScript를 실행하지 않는 크롤러는 빈
<div>외에는 아무것도 보지 못합니다.
Google Search Console을 열어보니 25개의 페이지 리소스 중 21개가 로드조차 되지 않았습니다—Google 크롤러가 접근할 수 없는 외부 CDN의 폰트 때문이었습니다. 내 사이트는 사람들에게 콘텐츠를 발견하게 해주는 시스템들에 거의 보이지 않는 상태였습니다.
내가 만든 해결책
나는 Cloudflare Worker를 작성했으며, 이것은 SPA 앞에 역방향 프록시처럼 위치합니다. 앱은 변하지 않으며, 호스팅도 변하지 않습니다. 워커는 요청을 가로채어 검색 엔진과 소셜 플랫폼이 보는 것을 수정합니다.
작동 방식
- 각 페이지마다 고유한 제목, 설명, Open Graph 태그, Twitter 카드, 정규화 URL이 제공됩니다.
/pricing페이지를 Slack에 공유하면 미리보기에 실제로 “Pricing”이라고 표시됩니다 — 홈페이지 제목이 아닙니다. - 검색 엔진 크롤러나 소셜 미리보기 봇(Googlebot, Bingbot, LinkedIn, Twitter, Slack, Discord, AI 봇 등 35개 이상)이 방문하면 실제 콘텐츠가 포함된 완전한 렌더링 HTML을 받게 됩니다. 빈 div가 아니라 실제 내용이 표시됩니다.
- 일반 방문자는 기존 SPA 그대로 이용합니다. 앱에 대한 변경 사항이 전혀 없습니다. 성능에 영향도 없습니다.
하지 않는 것
- 프레임워크를 변경할 필요가 없습니다.
- SSR이나 빌드 플러그인이 필요하지 않습니다.
- 기존 코드를 건드리지 않습니다.
- 앱이 어디에 호스팅되었든 상관없습니다 — Netlify, Vercel, Cloudflare Pages, S3 등 어디든.
파일 하나면 됩니다. 몇 분 안에 배포할 수 있으며, 모든 호스팅 플랫폼의 SPA에서 작동합니다.
얻는 것
내 사이트에 설정한 후:
- 11개 페이지 중 10개가 Google에 표시됩니다.
- 구조화된 데이터에서 FAQ 리치 결과가 감지되었습니다.
- 모든 페이지가 LinkedIn, Twitter, Slack, Discord에서 각각의 소셜 미리보기를 가집니다.
- 외부 리소스 실패가 25개 중 21개에서 거의 0에 가깝게 감소했습니다.
- 모든 페이지가 제출되어 Bing에서 크롤링되고 있습니다.
전체적으로 약 5 ms의 지연이 추가됩니다. SEO가 필요 없는 경로(예: 대시보드)에서는 워커가 직접 프록시하여 오버헤드가 전혀 없습니다.
AI 프롬프트로 설정할 수 있습니다
전체 설정을 하나의 AI 프롬프트로 묶었습니다. Claude Code, Cursor, Windsurf 또는 사용 중인 AI 편집기에 붙여넣으세요. 도메인, 라우트, 각 페이지의 제목과 설명 등 몇 가지 질문을 하면 모든 것을 자동으로 생성합니다:
- 워커.
- 프리렌더 스크립트.
- 사이트맵.
robots.txt.- 구조화된 데이터.
- 배포 및 Search Console 제출 단계.
HTMLRewriter, Playwright, JSON‑LD를 이해할 필요가 없습니다. 프롬프트가 기술적인 부분을 처리하므로, 여러분은 앱에 대한 질문에 답하기만 하면 됩니다.
AI 프롬프트는 다음과 같습니다:
(prompt omitted for brevity)
왜 이 글을 공유하는가
Because I know there are other devs who built something good and can’t figure out why nobody’s finding it. The SEO problem with SPAs isn’t obvious until you check—and by then you’ve already lost months of potential traffic.
다른 개발자들이 좋은 것을 만들었지만 왜 아무도 찾지 못하는지 이해하지 못하고 있다는 것을 알기 때문에입니다. SPA의 SEO 문제는 확인하기 전까지는 명확하지 않으며, 그때까지 이미 몇 달간의 잠재 트래픽을 잃게 됩니다.
If you built a single‑page app, go check Google Search Console right now. See how many of your pages are actually indexed. See what your social previews look like. You might be surprised.
만약 싱글 페이지 앱을 만들었다면, 지금 바로 Google Search Console을 확인해 보세요. 실제로 몇 개의 페이지가 색인되었는지 확인하고, 소셜 미리보기가 어떻게 나오는지 확인해 보세요. 놀랄 수도 있습니다.
Then fix it. It takes minutes, not days.
그 다음에 고치면 됩니다. 며칠이 아니라 몇 분이면 충분합니다.