소프트 404 확인하고 고치기 — 없는 주소가 200을 돌려주면 색인이 망가집니다
소프트 404는 없는 주소인데 서버가 404 대신 200을 돌려주는 상태입니다. 사람 눈에는 "페이지가 없습니다" 처럼 보여도 검색엔진에는 정상 페이지가 하나 더 있는 것으로 보입니다.
확인은 30초면 됩니다. 있을 리 없는 주소를 넣어보고 404가 오는지 보면 됩니다.
curl -s -o /dev/null -w "%{http_code}\n" https://내주소/_없는주소_확인용/
404가 나오면 정상입니다. 200이 나오면 소프트 404입니다.
왜 생기나
정적 사이트나 앞단 호스팅에서 없는 파일을 요청받았을 때 대문을 대신 내주도록 설정된 경우입니다. 한 페이지짜리 앱(SPA)을 위한 설정인데, 일반 블로그에 그대로 켜두면 문제가 됩니다.
404.html 파일 자체가 없을 때도 호스팅이 알아서 대문으로 넘기는 경우가 있습니다.
구조를 최소한으로 줄이면 이렇습니다.
def do_GET(self):
path = self.translate_path(self.path)
if not os.path.exists(path): # 없으면 대문을 200 으로 내준다 ← 여기가 원인
self.send_response(200)
self.wfile.write(open("index.html", "rb").read())
return
super().do_GET()
같은 요청을 두 서버에 넣어 보면 차이가 그대로 드러납니다.

응답 본문을 열어 보면 더 분명합니다. 없는 주소인데 대문 내용이 그대로 실려 옵니다.

무엇이 망가지나
200은 검색엔진에 "이 주소는 유효한 페이지" 라는 뜻입니다. 그래서 이런 일이 생깁니다.
| 일어나는 일 | 왜 |
|---|---|
| 없는 주소가 색인 후보가 됨 | 200이니 정상 페이지로 봅니다 |
| 같은 내용이 여러 주소에 존재 | 어떤 주소든 대문 내용이 나옵니다 |
| 크롤링 예산 낭비 | 없는 주소를 계속 다시 확인하러 옵니다 |
서치콘솔에 소프트 404 경고 |
구글이 "내용 없음"으로 판단하면 이렇게 표시합니다 |
특히 오타 주소·삭제한 글 주소가 계속 살아 있는 것처럼 보입니다. 링크를 잘못 걸어둔 곳이 있으면 그 주소가 색인될 수도 있습니다.
저는 사이트를 올린 직후에 이걸 겪었습니다. 아무 주소나 넣어도 대문이 나오길래 처음엔 "링크가 잘 잡히는구나" 하고 넘겼습니다. 없는 주소가 정상 응답을 받고 있다는 걸 나중에야 알았습니다. 눈으로 보면 대문이 잘 뜨는 것처럼 보여서 문제로 인식되지 않습니다.
주소를 몇 개 찍어 보다가 이상하다 싶어 응답 코드를 봤더니 전부 200 이었습니다. 그때 처음 이 이름을 찾아봤습니다.
점검하는 법
주소 하나만 보면 놓칩니다. 경로 형태별로 셋 이상 확인합니다. 규칙이 경로마다 다르게 걸려 있는 경우가 있습니다.
#!/bin/bash
# 사용: bash soft404check.sh https://내주소
UA="Mozilla/5.0 (404-check)"; SITE="${1%/}"
for p in /_없는주소_확인용/ /p/_no_such_post_/ /c/_no_such_cat_/; do
printf "%-26s %s\n" "$p" "$(curl -s -A "$UA" -o /dev/null -w '%{http_code}' "$SITE$p")"
done

셋 다 404여야 합니다. 하나라도 200이면 그 경로 규칙을 봐야 합니다.
브라우저로만 확인하면 안 됩니다. 화면에는 "없는 페이지" 라고 떠 있어도 응답 코드는 200일 수 있습니다. 눈으로는 구분이 안 됩니다. 응답 코드를 직접 봐야 합니다.
고치는 순서 — 3단계
제가 고칠 때 밟은 순서 그대로입니다. 위에서부터 하시면 됩니다.
1. 404 페이지를 만듭니다
빌드 산출물 최상단에 404.html 을 둡니다. 대부분의 정적 호스팅이 이 파일 이름을 찾아 씁니다.
내용에는 이런 걸 넣습니다.
- 주소가 잘못됐다는 안내 한 줄
- 대문·전체 글 목록으로 가는 링크
- 검색이 있으면 검색창
대문을 그대로 복사해 두면 안 됩니다. 내용이 대문과 같으면 코드가 404여도 검색엔진이 소프트 404로 판단할 수 있습니다.
2. 폴백 설정을 끕니다
호스팅에 "모든 요청을 index.html 로" 같은 설정이 있으면 끕니다. 이름은 서비스마다 다릅니다.
| 부르는 이름 | 어디에 |
|---|---|
| SPA fallback | 정적 호스팅 설정 |
| rewrite / redirect 규칙 | _redirects·vercel.json 같은 설정 파일 |
| try_files | 웹서버 설정 |
블로그처럼 주소마다 실제 파일이 있는 사이트는 폴백이 필요 없습니다.
3. 삭제한 글은 410 을 고려합니다
일부러 내린 글이라면 404 대신 410(영구 삭제)을 주는 편이 낫습니다. 검색엔진이 더 빨리 목록에서 뺍니다.
다만 정적 호스팅에서는 응답 코드를 주소별로 지정하기 어려운 경우가 많습니다. 저도 제 호스팅에서 410을 줄 방법이 있는지 아직 확인하지 못했습니다. 설정 파일로 될 것 같은데 문서에서 찾지 못했고, 급한 문제가 아니라 404로 두고 넘어갔습니다. 대부분은 404로 충분합니다.
고친 뒤에도 200이 남습니다
여기서 한 번 더 헷갈립니다. 고쳐서 배포했는데 확인하면 여전히 200이 나옵니다.
원인은 엣지 캐시입니다. 요즘 호스팅은 전 세계 여러 곳에 응답을 복사해 두는데, 예전 응답이 아직 남아 있는 지역이 있습니다. 배포가 끝났다는 신호와 모든 지역에 반영되는 시점은 같지 않습니다. 저는 다른 작업에서 이 시차 때문에 페이지마다 반영 시각이 다른 것도 봤습니다 — 어떤 주소는 바로 바뀌고 어떤 주소는 몇 분 뒤에 바뀝니다.
조치는 셋입니다.
- 몇 분 기다렸다가 다시 확인합니다
- 주소 뒤에
?cb=아무값을 붙여 캐시를 우회해 봅니다 - 호스팅 관리 화면에 캐시 비우기가 있으면 누릅니다
저는 이걸 모르고 설정을 다시 뒤졌습니다. 코드는 맞는데 결과가 안 바뀌니 잘못 고친 줄 알았습니다. 배포 직후 한 번 확인하고 판단하지 마세요. 시간을 두고 두 번 보는 편이 낫습니다.
고쳤는지 확인
| 확인 | 방법 | 정상 |
|---|---|---|
| 응답 코드 | 위 점검 스크립트 | 전부 404 |
| 404 본문 | 없는 주소를 브라우저로 열기 | 대문과 다른 안내 화면 |
| 서치콘솔 | 색인 생성 → 페이지 |
소프트 404 항목이 줄어듦 |
서치콘솔 쪽은 반영이 느립니다. 며칠에서 몇 주 걸리므로 코드 응답이 맞으면 고친 것으로 보고 넘어가면 됩니다.
흔한 오해 셋
| 이렇게 알기 쉽다 | 실제 |
|---|---|
| 화면에 "없는 페이지" 라고 뜨면 404다 | 화면과 응답 코드는 별개입니다 |
| 404 페이지를 예쁘게 만들면 된다 | 코드가 404여야 의미가 있습니다 |
| 고치면 바로 반영된다 | 엣지 캐시 때문에 잠시 200이 남습니다 |
판정 — 계속 쓴다
점검은 30초, 수정은 10분입니다. 404.html 하나 만들고 폴백 설정을 끄면 끝납니다. 비용 대비 효과가 이만한 게 드뭅니다.
사이트를 새로 만들면 배포 직후에 한 번은 꼭 확인하는 편이 낫습니다. 나중에 서치콘솔에서 소프트 404 경고를 보고 찾으면, 그때는 이미 없는 주소들이 색인 후보로 돌아다닌 뒤입니다.
직접 하실 분께
하나. 확인은 응답 코드로 합니다. 브라우저 화면으로 판단하면 놓칩니다.
둘. 404 페이지 내용을 대문과 다르게 만듭니다. 같으면 코드가 404여도 소프트 404로 판단될 수 있습니다.
셋. 배포 스크립트에 점검을 넣어두면 다시 안 겪습니다. 없는 주소 하나를 찔러 보고 404가 아니면 경고를 띄우는 정도면 충분합니다.
넷. 고친 직후 200이 나와도 바로 되돌리지 마세요. 캐시일 가능성이 큽니다. 시간을 두고 다시 확인합니다.
다음에는 삭제한 글에 410을 주는 방법이 정적 호스팅에서 가능한지 확인해보려고 합니다. 되면 이어서 적겠습니다.