존재하지 않는 페이지로 접근한 사용자에게 예쁜 디자인의 안내 문구를 보여주거나 자동으로 메인 페이지로 이동시키는 처리를 해보신 적이 있으신가요? 사용자 경험(UX)을 고려한 아주 당연한 개발 방식처럼 보입니다.
다만 HTTP 상태 코드를 올바르게 제어하지 않으면 검색엔진 크롤러가 이를 'Soft 404' 에러로 판단하여 웹사이트의 크롤링 예산을 낭비하고 검색 색인에서 페이지를 무더기로 제외해버리는 심각한 문제가 발생합니다.
이번 글에서는 Soft 404 에러가 정확히 무엇인지, 왜 크롤러가 이를 문제 삼는지, 그리고 서버 환경과 코드 레벨에서 어떻게 완벽하게 해결할 수 있는지 깔끔하게 정리해 드리겠습니다.
Soft 404는 웹 서버의 실제 HTTP 상태 코드(Status Code)는 200 OK(성공)를 반환하지만, 실제 브라우저 화면에 표출되는 콘텐츠는 "페이지를 찾을 수 없습니다" 또는 "삭제된 게시물입니다"와 같은 404 에러 안내인 상태를 의미합니다.
검색엔진 크롤러(Googlebot 등)는 브라우저처럼 눈으로 화면을 보는 것이 아니라, 먼저 웹 서버가 전달하는 HTTP 헤더 상태 코드를 읽습니다. 서버가 200 OK를 응답하면 크롤러는 "아, 이 URL에 유용한 콘텐츠가 존재하구나!" 하고 본문을 분석합니다. 그러나 막상 본문 텍스트를 파싱해 보니 "요청하신 페이지가 존재하지 않습니다"라는 문구만 달랑 있거나 텅 비어 있다면, 크롤러는 이를 시스템 오류 및 기만 행위로 간주하고 Soft 404 판정을 내립니다.
Soft 404가 수십, 수백 개 쌓이게 되면 다음과 같은 치명적인 문제가 발생합니다.
- 크롤링 예산(Crawling Budget) 낭비: 검색엔진이 내 사이트를 방문하여 색인할 수 있는 주기는 제한되어 있습니다. 불필요한 에러 페이지를 200 OK로 인식하여 크롤링하게 되면 정작 중요한 신규 콘텐츠를 크롤링하지 못합니다.
- 검색 색인 제외 및 품질 평가 하락: 구글 서치 콘솔(Google Search Console)에 'Soft 404' 오류가 지속적으로 리포트되며, 사이트 전반의 도메인 신뢰도와 품질 점수가 감점됩니다.
개발 현장에서 흔히 실수하는 구성을 비교표로 정리해 보았습니다.
| 구분 | HTTP 상태 코드 | 화면 출력 내용 | 검색엔진 인식 | SEO 영향 |
|---|---|---|---|---|
| 정상 404 | 404 Not Found | 404 안내 페이지 또는 기본 에러 | 존재하지 않는 페이지로 정상 인식 | 색인에서 안전하게 제거됨 (정상) |
| Soft 404 (잘못됨) | 200 OK | "존재하지 않는 페이지입니다" 메시지 | 정상 페이지로 착각 후 Soft 404 판정 | 검색 색인 오류 발생 및 SEO 감점 |
| 잘못된 리다이렉트 | 302 Found (또는 200 OK) | 메인 페이지(/)로 강제 이동 | Soft 404 또는 중복 콘텐츠 처리 | 메인 페이지 검색 순위 악영향 |
실무에서 동적 웹 애플리케이션(PHP 등)을 개발할 때 데이터베이스에 존재하지 않는 ID 값이 들어왔을 때의 처리 코드를 살펴보겠습니다.
보통 초보 개발자분들은 DB 조회가 실패했을 때 상단 헤더 변경 없이 그냥 에러 메시지문만 echo로 출력하고 종료합니다. 이 경우 HTTP 응답 헤더는 기본값인 200 OK로 전송됩니다.
<?php
// ✗ 잘못된 코드: HTTP 상태 코드는 200 OK로 전송됨
$post_id = $_GET['id'] ?? 0;
$post = get_post_from_db($post_id);
if (!$post) {
// 헤더 설정 없이 에러 화면만 출력 -> Soft 404 원인!
echo "<h1>페이지를 찾을 수 없습니다.</h1>";
echo "<p>요청하신 게시물이 삭제되었거나 존재하지 않습니다.</p>";
exit;
}
?>✗ 문제점: 브라우저에는 에러 문구가 보이지만, HTTP Response Header 상태 코드는 HTTP/1.1 200 OK가 되어 검색엔진이 Soft 404로 분류합니다.
존재하지 않는 리소스에 접근했을 때는 반드시 http_response_code(404) 또는 header() 함수를 사용하여 HTTP 헤더를 404로 명확하게 전달해야 합니다.
<?php
// ✓ 올바른 코드: HTTP 헤더에 404 Not Found를 명확하게 전달
$post_id = $_GET['id'] ?? 0;
$post = get_post_from_db($post_id);
if (!$post) {
// 1. HTTP 응답 코드를 404로 변경
http_response_code(404);
// 2. 사용자용 커스텀 404 템플릿 로드
include('errors/404.php');
exit;
}
?>✓ 결과: 서버 헤더 응답값 HTTP/1.1 404 Not Found가 정상 송출됩니다. 크롤러는 더 이상 이 페이지를 색인하지 않고 수집 대상에서 깔끔하게 제외합니다.
단순 PHP 코드뿐만 아니라 정적 파일이나 존재하지 않는 경로로 접근했을 때 웹서버 자체에서 깔끔한 커스텀 404 페이지를 보여주도록 설정하는 것도 매우 중요합니다.
Nginx 환경에서는 error_page 404 지시어를 통해 커스텀 404 HTML 파일을 지정할 수 있습니다.
# Nginx server 블록 내부 설정
server {
listen 80;
server_name example.com;
root /var/www/html;
# 404 에러 발생 시 지정한 경로의 파일로 내부 응답 (상태 코드는 404 유지)
error_page 404 /404.html;
location = /404.html {
internal;
}
}
Apache 서버 환경에서는 .htaccess 파일 내에 ErrorDocument 404 구문을 추가해 줍니다.
# Apache .htaccess 설정
ErrorDocument 404 /404.html※ 주의: Apache 설정 시 ErrorDocument 404 http://example.com/404.html 과 같이 절대 URL(http 포함)을 적으면 외부 리다이렉트(302)가 발생하여 404 헤더가 손실될 수 있습니다. 반드시 /404.html 처럼 상대 경로 형태로 지정해야 합니다.
Soft 404 문제를 해결하려다 또 다른 SEO 실수를 저지르는 경우가 빈번합니다.
- ✗ 존재하지 않는 페이지를 무조건 메인 페이지(/)로 302 리다이렉트하는 행위:
과거 일부 웹사이트에서 잘못된 접근을 모두 메인 페이지로 302 전달(Redirect)시키는 방식을 사용하곤 했습니다. 구글은 수많은 서로 다른 에러 URL이 메인 페이지로 모이는 것을 보고 메인 페이지 자체를 Soft 404로 오인하거나 중복 URL로 판단하여 불이익을 줍니다. - ✗ JavaScript window.location을 이용한 에러 처리:
PHP/서버단 처리가 아닌 클라이언트 자바스크립트로location.href = '/404'처리를 할 경우, 최초 로딩 시 서버는 200 OK를 반환하기 때문에 검색엔진은 이미 Soft 404로 기록해 버립니다. - ✓ 올바른 조치 방법:
실제로 없어진 페이지는 HTTP status 404(또는 영구 삭제된 경우 410 Gone)를 응답하고, 안내 페이지 내부에는 메인으로 이동하는 버튼, 추천 게시물 링크, 검색창 등을 배치하여 방문한 사용자가 다른 페이지로 이동할 수 있도록 안내하는 것이 완벽한 정석입니다.
Soft 404 에러 방지는 웹사이트의 검색엔진 색인 건강도와 SEO 성능을 유지하는 데 핵심적인 요소입니다. 개발 과정에서의 작은 헤더 상태 코드 지정 습관 하나가 검색 노출 품질에 큰 차이를 만든다는 점을 잊지 말자. 이 글의 실전 예제와 웹서버 설정을 참고해 본인 사이트의 404 처리 로직을 점검하면, 검색엔진 감점 없는 완벽한 웹 서비스를 유지할 수 있을 것이다.