몇 달 전부터 개인 프로젝트로 커뮤니티 사이트를 하나 직접 만들어 운영 중이다. 프론트도 직접 짜고 백엔드도 서버리스 환경에 올렸다. 기능 구현은 다 끝났고 글도 수백 개가 쌓였는데, 정작 제일 중요한 한 가지가 안 됐다. 구글 검색에 내 글이 단 하나도 안 떴다. 사이트 이름을 그대로 검색해도 안 나오고, site: 도메인 연산자로 훑어도 색인된 페이지가 사실상 0이었다.
처음엔 무조건 코드 문제라고 믿었다. 메타 태그가 누락됐나, canonical이 꼬였나, 봇한테 SSR 결과물이 안 나가나 싶어 며칠을 렌더링 파이프라인만 팠다. 그런데 curl로 User-Agent를 Googlebot으로 위장해 받아본 HTML에도, 구글 서치 콘솔 URL 검사 도구로 확인한 렌더링 결과에도 본문과 title, canonical이 멀쩡히 들어 있었다. 크롤은 되는데 색인이 안 되는 상태. 원인이 페이지 안쪽이 아니라 바깥, 즉 도메인 신뢰와 사이트 구조에 있다는 뜻이었다. 결론부터 말하면 이건 버그가 아니라 신뢰의 문제였고, 정확히는 네 가지가 동시에 겹친 구조적 문제였다.
![[실전 SEO 01] 새로 만든 사이트가 구글에 안 뜨는 4가지 이유](https://img.thenullpage.com/posts/5553/5553_1_969dbb.webp)
1. 신생 도메인은 구글이 처음부터 안 믿는다
가장 근본적인 원인. 구글은 갓 등록된 도메인을 신뢰하지 않는다. 이유는 단순하다. 스팸과 도배용 도메인이 매일 수만 개씩 새로 생성되기 때문이다. 신규 도메인을 무조건 즉시 전량 색인해준다면 검색 결과는 하루 만에 스팸으로 뒤덮인다. 그래서 구글은 도메인 나이(domain age)와 이력이 쌓이기 전까지 크롤 빈도와 색인 우선순위를 의도적으로 낮게 잡는다. 업계에서 흔히 샌드박스(sandbox)라 부르는 현상으로, 공식 용어는 아니지만 신생 사이트라면 거의 예외 없이 겪는 3~6개월짜리 유예 기간이 실제로 관측된다.
핵심 증상은 크롤 버짓(crawl budget)이 극도로 짜다는 것이다. 크롤 버짓은 서버가 버틸 수 있는 요청 속도(crawl rate limit)와 구글이 이 사이트를 얼마나 크롤하고 싶어 하는가(crawl demand), 두 축으로 결정된다. 신생 도메인의 병목은 서버 성능이 아니라 후자다. 관심이 없으니 서버가 아무리 빨라도 조금만 긁는다. 실제로 초기 로그를 보면 구글봇이 하루에 가져가는 URL이 수십 개 수준이라, 글 수백 개를 한 바퀴 도는 데만 며칠이 걸렸다. 그래서 초반에 응답 속도만 붙잡고 최적화해봐야 색인 속도는 거의 안 변한다. 병목이 거기가 아니기 때문이다. 그리고 이건 코드로 못 뚫는다. 도메인 신뢰는 시간과 신호의 함수라, 조급하게 편법을 쓰다 스팸 신호를 주는 게 오히려 더 위험하다.
2. 초기에 URL 구조를 두 번이나 갈아엎었다
![[실전 SEO 01] 새로 만든 사이트가 구글에 안 뜨는 4가지 이유 (2)](https://img.thenullpage.com/posts/5553/5553_2_ec955a.webp)
<한번 색인되었던 url들은 엄청난 시간이 지나야 빠진다>
두 번째는 자책 포인트다. 초기에 URL 설계를 확정하지 못하고 두 번 바꿨다. 처음엔 쿼리 스트링 기반 post.html?id=123 형태였다가, 정적 라우팅으로 바꾸며 /post/123으로 갔고, 다국어를 넣으며 다시 /ko/post/123으로 옮겼다. 개발자에겐 그냥 리팩터링이지만 구글에겐 완전히 다른 얘기다. 구글에게 URL은 콘텐츠의 고유 신원(identity)이라, 같은 글이 세 주소를 거쳐 왔다는 건 어렵게 색인해둔 주소가 두 번 폐기됐다는 뜻이다.
이때 옛 주소에서 새 주소로 301을 정확히 걸어주지 않으면 그동안 쌓인 색인 자산(link equity)이 통째로 증발한다. 여기서 canonical과 301을 구분해야 한다. canonical(rel=canonical)은 대표 주소는 이거야라는 힌트일 뿐 강제력이 없어 구글이 무시할 수 있고, 301은 영구 이전을 알리는 HTTP 레벨의 명령에 가까워 훨씬 강한 신호다. 반드시 301이어야지 302(임시 이동)를 쓰면 안 된다. 302는 원래 주소가 곧 돌아온다는 뜻이라, 구글이 색인 자산을 넘겨주지 않고 옛 주소를 계속 붙잡는다. 게다가 옛 주소가 또 다른 주소로 넘어가는 리다이렉트 체인(redirect chain)이 생기면 구글봇이 최종 목적지 전에 크롤을 포기하기도 한다.
더 무서운 건 이게 누적 신호로 남는다는 점이다. 구글은 주소를 자주 바꾸는 사이트를 불안정하다고 학습하고, 색인해봤자 또 바뀔 테니 보류하자는 쪽으로 기운다. 크롤 버짓도 없는 신생 도메인이 그 적은 예산마저 URL 변경 뒷수습에 쓰는 최악의 조합이었다. 교훈은 하나다. URL 구조는 오픈 전에 확정하고, 한 번 정하면 절대 바꾸지 않는다. 특히 숫자 ID 기반의 짧고 영속적인 주소가 가장 안전하다.
3. 죽은 옛 주소 수천 개가 크롤 예산을 빨아먹고 있었다
URL을 두 번 갈아엎은 대가로 옛 주소 수천 개가 그대로 404가 됐다. 문제는 구글이 한 번 발견한 URL을 쉽게 안 잊는다는 것이다. 색인에서 빠진 뒤에도 다시 살아났나 하고 주기적으로 재방문한다. 결국 구글봇은 하루치 쥐꼬리만 한 크롤 버짓을, 새 글이 아니라 이미 죽은 주소를 확인하는 데 낭비하고 있었다.
여기서 404와 410의 차이가 중요하다. 404 Not Found는 지금은 없지만 나중에 생길 수도 있다는 뉘앙스라 구글이 미련을 갖고 한동안 재방문하지만, 410 Gone은 영구 삭제됐다는 명시적 신호라 훨씬 빠르게 색인에서 제거한다. 확실히 폐기한 옛 주소는 404로 방치하지 말고 410으로 명시하는 게 크롤 예산 회수에 유리하다. 또 피해야 할 함정이 소프트 404(soft 404)다. 실제로는 없는 페이지인데 서버가 200 OK로 존재하지 않습니다 안내 페이지를 내보내는 경우로, 구글은 이걸 알맹이 없는 200으로 보고 사이트 전체 품질 평가를 깎는다. 없으면 정직하게 404나 410을 줘야 한다. 옛 주소를 새 주소로 보냈는데 거기도 글이 없어 결국 404로 끝나는 빙빙 도는 구조는 봇 힘을 두 배로 낭비시키는 최악이니, 글이 없으면 리다이렉트 없이 그 자리에서 바로 410으로 끝내는 게 맞다.
4. 외부에서 걸린 링크가 정확히 0개였다
마지막은 백링크(backlink) 0. 구글 랭킹의 뿌리인 페이지랭크(PageRank)는 근본적으로 링크를 신뢰의 투표로 해석하는 알고리즘이다. 다른 사이트가 내 페이지를 링크한다는 건 참고할 만하다는 추천이고, 그런 추천이 많고 질 좋을수록 도메인 권위(authority)가 올라간다. 그런데 갓 만든 개인 프로젝트라 어디에도 언급된 적이 없으니, 구글 입장에선 아무도 추천하지 않는, 중요도를 판단할 근거조차 없는 사이트였다. 신생 도메인이면서 백링크까지 0이면 색인 우선순위 최하단에 놓이는 게 당연하다. E-E-A-T로 요약되는 경험(Experience)과 전문성(Expertise), 권위(Authoritativeness), 신뢰(Trust) 중 권위와 신뢰가 통째로 비어 있던 셈이다. 그리고 이 백링크는 코드로는 절대 못 만든다. 오직 바깥의 사람들이 내 콘텐츠를 언급해줘야 생기는, 순수하게 콘텐츠와 운영의 영역이다.
정리, 이건 코드가 아니라 신뢰의 문제였다
네 가지를 합치면 이렇다. 구글봇은 내 가게에 오는 손님인데, 간판을 자꾸 바꾸고(URL 변경), 옛 주소로 찾아가면 문이 닫혀 있고(404 누적), 아무도 추천하지 않는(백링크 0), 게다가 문 연 지 얼마 안 된(신생 도메인) 가게였다. 손님이 새 메뉴(새 글)를 구경도 안 하고 돌아가는 게 당연했다. 중요한 건 이 중 어느 것도 마크업 한 줄로 해결되지 않는다는 점이다. 그래서 접근을 바꿨다. 구글이 지금 내 사이트를 어떤 상태로 보는지부터 데이터로 확인하고, 크롤 예산을 낭비하는 요소를 하나씩 걷어내고, 신뢰 신호를 시간을 들여 쌓는 쪽으로. 다음 편에서는 그 진단의 출발점인 구글 서치 콘솔(GSC)을 처음 세팅하고 색인 상태 리포트를 실제로 어떻게 읽는지 다루겠다. 코드를 고치기 전에 환자 상태부터 봐야 하니까.