소프트 404 오류란? 원인을 찾는 방법과 올바른 해결법

SEOgrinder 편집팀 · 게시일 · 읽는 시간 약 12분

핵심 답변: 소프트 404란 방문자에게는 ‘찾을 수 없음’(또는 거의 아무것도 없는 화면)을 보여 주면서, 서버는 404가 아니라 성공을 뜻하는 상태 코드 200으로 응답하는 페이지를 말합니다. Google은 이런 페이지를 오류로 취급하며, 2xx 응답의 내용이 오류를 가리키면 Search Console이 소프트 404로 보고합니다. 해결 방법은 서버가 사실에 맞는 상태 코드를 보내게 하는 것입니다. 사라진 페이지는 404나 410, 이전한 페이지는 동등한 페이지로 301, 있어야 하는 페이지는 실제 콘텐츠를 채웁니다.

소프트 404란 무엇인가요?

웹 서버의 모든 응답은 상태 코드로 시작하며, 상태 코드는 어떤 콘텐츠보다 먼저 도착합니다. 200은 ‘정상입니다, 페이지는 이것입니다’라는 뜻이고, 404는 ‘여기에는 아무것도 없습니다’라는 뜻입니다. 소프트 404는 이 둘이 어긋난 상태입니다. 화면에는 ‘찾을 수 없음’이나 ‘결과 0건’이 표시되어 있거나 읽을 만한 내용이 전혀 없는데, 상태는 200입니다.

Google은 이 경우를 HTTP 상태 코드와 네트워크 오류에 관한 문서에서 설명합니다. 2xx 응답이면 Google은 콘텐츠를 처리에 반영합니다. 그 콘텐츠가 빈 페이지나 오류 메시지처럼 오류를 가리키면 Search Console에 소프트 404 오류로 표시됩니다. 진짜 4xx 상태라면 Google은 그 URL의 콘텐츠를 전혀 사용하지 않습니다.

터미널에서는 차이가 이렇게 보입니다. 이런 문제가 있는 사이트에서 존재하지 않는 주소를 요청하면 다음과 같이 나옵니다(주소는 예시입니다).

$ curl -s -o /dev/null -w "%{http_code}\n" https://your-site.example/page-that-does-not-exist
200

올바른 응답은 404입니다. 방문자는 두 경우 모두 똑같이 친절한 ‘페이지를 찾을 수 없습니다’ 문구를 봅니다. 다른 것은 상태뿐인데, 크롤러가 가장 먼저 읽는 것이 바로 상태입니다.

이름의 ‘소프트(soft)’는 ‘가볍다’는 뜻이 아닙니다. 서버는 모두 정상이라고 말하는데 페이지는 정상이 아니라고 말한다는 뜻입니다.

소프트 404는 왜 문제가 되나요?

문서로 확인된 것과 확인되지 않은 것을 나누어 보겠습니다.

확인된 것:

  • Search Console이 해당 URL을 소프트 404 오류로 나열합니다. 즉 Google 스스로 이것을 문제로 봅니다.
  • 진짜 404나 410이면 Google은 그 URL의 콘텐츠를 사용하지 않습니다. 200이면 콘텐츠를 보고 그 페이지가 오류인지 Google이 추측해야 합니다.

확인되지 않은 것: 순위에 대한 직접적인 영향입니다. Google은 리포트에서 이 오류를 언급할 뿐이며, 소프트 404가 사이트의 다른 페이지를 끌어내린다고 밝힌 적이 없고 우리도 그것을 증명하는 출처를 찾지 못했습니다. ‘소프트 404가 SEO를 망친다’ 같은 주장은 의심하며 들으세요.

우리의 견해이며 그 이상은 아닙니다: 가치 없는 페이지는 검색 결과로 제시되지 않는 편이 낫고, 고치는 비용은 작습니다. Google과 무관한 현실적인 이유도 있습니다. 깨진 링크 검사기와 가동 상태 모니터링 도구는 상태 코드를 읽습니다. 모든 주소가 200으로 응답하면 이런 도구는 링크가 깨졌다고 알려 줄 수 없고, 오래된 링크를 따라온 방문자도 그 페이지가 사라졌다는 사실을 끝내 알지 못합니다.

소프트 404는 왜 생기나요?

소프트 404는 보통 다음과 같은 패턴에서 생깁니다.

  • 모든 경로에 같은 껍데기를 돌려주는 싱글 페이지 앱(SPA). 서버는 어떤 주소가 오든 상태 200으로 앱을 보냅니다. JavaScript가 실행된 뒤에야 화면에 ‘찾을 수 없음’이 나타나지만, 상태는 그 전에 이미 정해졌고 200입니다. Google은 크롤링, 렌더링, 색인의 단계로 페이지를 처리하는데, 상태 200인 페이지는 렌더링 대기열에 들어갑니다. 이 모델은 Google의 JavaScript SEO 기본 문서에 설명되어 있습니다. 스크립트를 아예 실행하지 않을 수 있는 크롤러가 있다는 점은 별개의 문제입니다.
  • 상태 200을 보내는 보기 좋은 오류 페이지. CMS, 프레임워크, 프록시 규칙이 디자인된 ‘찾을 수 없음’ 템플릿을 보여 주면서 상태 설정을 빼먹은 경우입니다.
  • 비어 있는 목록 페이지. 항목이 없는 카테고리, 태그, 내부 검색 페이지가 여전히 200으로 응답하며 ‘결과 0건’이나 빈 틀을 보여 줍니다.
  • 품절되거나 단종된 상품. 페이지는 남아 있지만 ‘구매할 수 없음’ 정도의 안내밖에 없습니다. 실제 상품 설명과 재고 안내가 그대로 남아 있는 페이지는, 안내 문구 한 줄만 남은 페이지와는 다른 경우입니다.
  • 전부 홈페이지로 리디렉션하기. 삭제한 페이지를 시작 페이지로 보내면 관련 없는 내용과 함께 200으로 끝납니다. 홈페이지는 사라진 페이지와 동등한 페이지인 경우가 드뭅니다.

또 다른 원인은 빈약한 페이지입니다. 자리표시자나 만들다 만 섹션처럼 내용이 거의 없는 템플릿입니다. 오류 메시지나 빈 페이지처럼 보이는 콘텐츠는 아무도 오류 페이지로 만들 의도가 없었더라도 오류로 분류될 수 있습니다.

소프트 404는 어떻게 찾나요?

서로 보완하는 세 가지 방법이 있습니다.

  1. Search Console. 페이지 색인 생성 보고서(「페이지」)에서 ‘소프트 404’라는 사유를 찾아봅니다. Google이 직접 그 분류에 넣은 URL이 나열됩니다. 「URL 검사」 도구는 개별 주소에 대해 Google이 무엇을 받는지 보여 줍니다.
  2. 터미널. 존재할 수 없는 주소를 요청하고 상태를 읽습니다(아래 명령).
  3. 브라우저. 개발자 도구를 열어 네트워크 탭으로 가서, 지어낸 주소를 불러온 다음 첫 번째 요청의 상태를 확인합니다. 페이지 화면만으로는 알 수 없습니다. 어떤 상태든 화면은 똑같이 보이기 때문입니다.

터미널 점검에서는 -L 옵션이 리디렉션을 따라가므로 주소가 최종적으로 어디에 도착하는지도 볼 수 있습니다.

curl -s -L -o /dev/null -w "%{http_code} %{url_effective}\n" https://your-site.example/page-that-does-not-exist

원하는 결과는 404입니다. 200 https://example.com/이 나온다면 서버가 알 수 없는 주소를 홈페이지로 보내고 있는 것입니다. 일부 서버는 HEAD 요청에 다르게 응답하므로 curl -I가 아니라 이처럼 GET으로 요청하세요.

바깥에서 테스트하세요. 애플리케이션을 직접 호출하지 말고 공개 주소를 요청해야 합니다. 애플리케이션 앞에 있는 CDN, 캐시, 방화벽이 응답을 바꿀 수 있기 때문입니다.

SEOgrinder는 소프트 404를 어떻게 점검하나요?

SEOgrinder의 무료 스캔은 존재할 수 없는 무작위 이름의 주소를 사이트에 요청해 봅니다. 응답이 200이면 문제로 보고합니다. 그 주소가 홈페이지로 리디렉션되는 경우도 마찬가지로 200으로 끝나므로 같은 문제로 칩니다. 결과는 「Google에서의 페이지」 탭의 「색인」 카드에 한 줄로 나옵니다. 「없는 주소가 404를 올바르게 반환합니다」 또는 「없는 주소가 404 대신 200를 반환합니다」입니다. 문제가 발견되면 진짜 404나 410을 반환하라는 조언과 함께 할 일 목록에 올라갑니다.

솔직한 한계가 두 가지 있습니다. 첫째, 이 테스트가 확인하는 것은 서버가 존재하지 않는 주소를 어떻게 처리하는가입니다. 내가 가진 실제 URL 중 어느 것을 Google이 소프트 404로 분류했는지는 알려 주지 않습니다. 개별 URL에 대한 판정은 Search Console에 있습니다. Search Console과 연결된 로컬 설치에서는 SEOgrinder가 검사한 페이지의 저장된 색인 상태도 읽어서, Google이 그 페이지를 소프트 404로 나열하면 그 사실을 알려 줍니다. 둘째, 이 테스트로는 내 사이트의 빈약한 페이지가 Google 눈에 비어 보이는지는 알 수 없습니다. 사이트 순회는 빈약한 페이지와 깨진 내부 링크를 표시하는데, 문제가 시작되는 곳이 바로 그런 곳인 경우가 많습니다.

어떤 상태 코드가 맞을까요? 판단표

올바른 응답은 그 페이지에 대해 무엇이 사실인지에 달려 있습니다. 상태를 사실에 맞추세요. 그 반대가 아닙니다.

상황올바른 응답비고
페이지가 영구적으로 사라졌고 동등한 페이지가 없음404 또는 410디자인된 오류 페이지도 괜찮지만 오류 상태를 보내야 함
페이지가 새 주소로 이전함동등한 새 페이지로 301(또는 308)Google이 대상을 처리하라는 강한 신호
이전이 정말 일시적임302(또는 307)약한 신호이므로 영구 이전에는 쓰지 않음
페이지는 있지만 빈약하거나 거의 비어 있음실제 콘텐츠 추가쓸모가 없다면 제거
영구적으로 비어 있는 목록 또는 검색 페이지404링크와 사이트맵에서 제외
지금만 비어 있는 목록 페이지유용한 내용을 보여 줌예를 들어 관련 항목과 안내문을 상태 200으로 제공
영구적으로 사라진 상품404 또는 410, 또는 직접적인 후속 상품으로 301홈페이지로는 보내지 않음
한동안 품절인 상품실제 콘텐츠가 있는 페이지 유지이 경우에는 상태 200이 맞음

Google은 301과 308을 리디렉션 대상을 처리하라는 강한 신호로, 302와 307을 약한 신호로 취급합니다. 기본적으로 최대 10단계의 리디렉션을 따라가며, 리디렉션하는 URL의 콘텐츠는 무시합니다. 그러니 최종 주소로 곧바로 한 번만 리디렉션하세요.

nginx, Node, SPA에서 소프트 404를 해결하는 방법

nginx

아래 설정은 디자인된 오류 페이지를 보여 주면서 상태 404를 유지합니다. error_page 404 /404.html;은 =200을 덧붙이지 않는 한 원래 상태를 유지하므로 덧붙이지 마세요.

server {
    root /var/www/example;
    error_page 404 /404.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location = /404.html {
        internal;
    }

    # 의도적으로 제거함
    location /old-campaign/ {
        return 410;
    }

    # 이전함
    location = /old-page {
        return 301 https://example.com/new-page;
    }
}

Node

데이터가 있는 경로에서는 코드가 먼저 레코드를 조회하고 그다음에 상태를 정해야 합니다. 이 예시는 Node 내장 모듈만 사용합니다.

import http from 'node:http';

const products = new Map([['blue-mug', '파란 머그컵']]); // 실제 데이터베이스를 대신하는 자리표시자

http.createServer((req, res) => {
  const { pathname } = new URL(req.url, 'http://localhost');
  const match = /^\/products\/([a-z0-9-]+)$/.exec(pathname);
  const name = match && products.get(match[1]);
  res.writeHead(name ? 200 : 404, { 'content-type': 'text/html; charset=utf-8' });
  res.end(name ? `<h1>${name}</h1>` : '<h1>페이지를 찾을 수 없습니다</h1>');
}).listen(3000);

오류 페이지는 친절하게 디자인해도 되고, 상태는 여전히 404입니다. 대부분의 프레임워크에는 같은 목적의 ‘not found’ 함수나 훅이 있습니다. 템플릿만 출력하는 것이 아니라 상태까지 설정하는 것을 찾아서 쓰세요.

싱글 페이지 앱(SPA)

서버는 어떤 경로가 실제로 있는지 알아야 합니다. 흔한 지름길인 ‘모든 요청에 index.html을 보낸다’가 바로 문제를 만듭니다. nginx에서는 실제 경로를 나열하고 나머지에는 404로 응답할 수 있습니다.

location = / {
    try_files /index.html =404;
}

location ~ ^/(about|contact|docs)/?$ {
    try_files /index.html =404;
}

location / {
    try_files $uri =404;
}

스크립트와 이미지 같은 에셋은 마지막 블록이 찾아 주고, 그 밖의 모든 경로는 404를 받습니다. 경로 목록이 길거나 자주 바뀐다면 빌드할 때 라우터로부터 생성하세요. 다른 방법은 서버에서 또는 미리 실제 페이지를 만들어 두는 것입니다. 그러면 모든 주소에 각자의 HTML 파일이 생기고 서버가 그에 맞게 응답할 수 있습니다. Google 스스로도 서버 사이드 렌더링이나 프리렌더링이 좋은 방법이라고 말합니다. 사용자와 크롤러 모두에게 페이지가 더 빨라지고, 모든 봇이 JavaScript를 실행할 수 있는 것은 아니기 때문입니다. 앱에서 상태 코드를 설정할 수 없거나 현실적으로 어려운 경우에 대해 Google의 JavaScript SEO 기본 문서는 방법을 두 가지 더 제시합니다. 404로 응답하는 주소(예: /not-found)로 JavaScript로 리디렉션하거나, 오류 페이지에 JavaScript로 <meta name="robots" content="noindex">를 추가하는 것입니다.

변경할 때마다 curl 점검을 다시 실행하고, 실제 페이지 하나, 이전한 페이지 하나, 존재할 수 없는 주소 하나를 테스트하세요.

자주 하는 실수

  • 상태가 아니라 디자인을 고치는 것. 상태 200을 보내는 아름다운 ‘찾을 수 없음’ 페이지는 여전히 소프트 404입니다.
  • 없는 페이지를 모두 홈페이지로 리디렉션하는 것. 이렇게 하면 내가 쓰는 도구에서 문제가 가려지고, 방문자는 찾던 것과 다른 것을 받게 됩니다. 동등한 페이지로 리디렉션하거나 404로 응답하세요.
  • error_page 404 =200 /index.html; 같은 지름길. 알 수 없는 모든 주소의 상태를 200으로 바꿔 버립니다.
  • 브라우저에서만 테스트하는 것. 브라우저 화면은 어떤 상태든 똑같아 보입니다. 상태를 읽으세요.
  • 상태를 고치는 대신 robots.txt에서 해당 주소를 막는 것. 페이지를 가져갈 수 없는 크롤러는 그 상태 코드를 끝내 보지 못합니다.
  • 사이트맵에 죽은 주소를 남겨 두는 것. 사이트맵에는 존재하고 200으로 응답하는 페이지만 담아야 합니다.
  • 리포트가 곧바로 사라지길 기대하는 것. Search Console의 항목은 Google이 그 URL을 다시 가져갈 때 바뀝니다. 그 시점은 누구도 약속할 수 없습니다.

자주 묻는 질문

소프트 404가 순위에 해를 끼치나요?

입증되지 않았습니다. Google이 Search Console에서 오류로 보고한다는 것은 문서로 확인됩니다. 사이트의 나머지 부분에 대한 직접적인 순위 불이익은 우리가 참고한 어떤 출처에도 나와 있지 않습니다. 합리적인 해석은 이렇습니다. 약속된 이득 때문이 아니라 응답이 잘못되었기 때문에 고치는 것입니다.

소프트 404와 404는 같은 건가요?

아니요. 404는 정직한 응답입니다. 상태가 그 페이지가 존재하지 않는다고 말합니다. 소프트 404는 200이라고 말하면서 내용은 정반대를 말합니다.

404와 410 중 무엇을 보내야 하나요?

둘 다 4xx 오류 상태이며, Google은 어느 쪽이든 그 URL의 콘텐츠를 사용하지 않습니다. 404는 ‘찾을 수 없음’에 대한 일반적인 응답입니다. 410은 ‘영구적으로 사라짐’을 뜻하므로 의도적으로 내린 페이지에 맞습니다.

직접 만든 404 페이지를 써도 되나요?

네, 그렇게 하는 편이 좋습니다. 원하는 대로 디자인하고 홈페이지 링크나 검색창을 넣어도 되지만, 상태는 반드시 404여야 합니다.

사이트 전체는 어떻게 점검하나요?

무료 스캔으로 서버가 알 수 없는 주소에 어떻게 응답하는지 확인하고, Google이 표시한 URL은 Search Console 리포트에서 확인하세요. 한 가지는 직접 살펴보세요. 짧은 안내문 말고는 아무것도 없는 페이지입니다.

다음 단계

내 사이트에 존재할 수 없는 주소를 curl로 요청해 보세요. 404가 아니라면 그것부터 고치세요. 그런 다음 SEOgrinder로 무료 스캔을 실행해 「Google에서의 페이지」 탭의 「색인」 카드에서 소프트 404 줄을 찾고, 수정한 뒤에는 다시 확인을 눌러 새 결과를 확인하세요. 사이트 전체를 점검하는 순서가 궁금하다면 SEO 체크리스트를 참고하세요.

블로그의 다른 글