ads.txt를 올렸는데 404가 나올 때, 워드프레스가 아니라 문서 루트를 먼저 봐야 하는 이유

ads.txt를 올렸는데 404가 나올 때, 워드프레스가 아니라 문서 루트를 먼저 봐야 하는 이유

워드프레스 사이트 루트에 ads.txtrobots.txt를 올렸는데 브라우저에서는 404가 뜨는 경우가 있습니다. FTP 화면에는 파일이 분명히 보이고 파일명도 맞는데 주소창으로는 열리지 않습니다. 이때 대부분 퍼머링크 설정을 다시 저장하거나 플러그인을 껐다 켜는 쪽으로 시간을 씁니다. 하지만 이 문제는 워드프레스 내부 설정보다 파일을 올린 위치와 웹서버가 실제로 바라보는 문서 루트가 어긋난 상황인 경우가 훨씬 많습니다. 이 글에서는 404의 출처를 먼저 구분하고, 문서 루트를 확인한 뒤, 멀티사이트와 캐시 계층까지 순서대로 좁혀 가는 방법을 정리합니다.

같은 404라도 만들어 낸 주체가 다르다

가장 먼저 할 일은 이 404를 누가 만들었는지 가리는 것입니다. 워드프레스가 만든 404와 웹서버가 만든 404는 화면이 비슷해 보여도 원인이 정반대입니다. 전자는 요청이 워드프레스까지 들어왔다는 뜻이고, 후자는 워드프레스 앞에서 끝났다는 뜻입니다.

화면 모습 만든 주체 의미 다음에 볼 곳
테마 디자인이 입혀진 ‘찾을 수 없음’ 페이지 워드프레스 요청이 PHP까지 들어왔다 실제 파일이 그 경로에 없음
흰 배경에 Not Found 한 줄 아파치·엔진엑스 워드프레스까지 가지도 않았다 문서 루트, 권한, 서버 설정
파일은 열리는데 내용이 다름 둘 다 아님 다른 파일이 응답 중 멀티사이트, 플러그인, 캐시

여기서 자주 오해가 생깁니다. 테마가 입혀진 404가 나온다면 파일이 없는 것이 거의 확실합니다. 워드프레스 기본 .htaccess에는 요청한 경로에 실제 파일이나 폴더가 있으면 워드프레스로 넘기지 말라는 조건이 들어 있기 때문입니다. 조건문 자체는 다음과 같은 형태입니다.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

즉 파일이 실제로 그 자리에 있으면 워드프레스는 그 요청을 아예 보지 못합니다. 반대로 워드프레스의 404 화면이 떴다는 것은 웹서버가 그 경로에서 파일을 찾지 못했다는 신고에 가깝습니다. 파일을 올린 기억이 있는데 워드프레스 404가 나온다면, 파일이 없는 것이 아니라 웹서버가 보는 자리에 없는 것입니다.

문서 루트와 워드프레스 폴더는 같지 않을 수 있다

이 어긋남이 생기는 가장 흔한 구조는 워드프레스를 하위 폴더에 설치하고 사이트 주소만 루트로 맞춰 놓은 경우입니다. 관리자 화면의 일반 설정에는 워드프레스 주소와 사이트 주소를 따로 지정하는 칸이 있고, 두 값이 다르게 설정된 사이트가 생각보다 많습니다.

주소 두 개가 다를 때 파일이 가야 할 곳

워드프레스 주소가 하위 폴더를 가리키고 사이트 주소가 루트 도메인을 가리킨다면, ads.txt는 워드프레스 파일이 모여 있는 폴더가 아니라 도메인이 실제로 바라보는 문서 루트에 있어야 합니다. 워드프레스 코어 파일 옆에 두면 눈에는 자연스러워 보여도 주소로는 열리지 않습니다.

호스팅에 따라 문서 루트 이름이 public_html, www, htdocs, httpdocs 등으로 제각각입니다. 이름만 보고 짐작하지 말고 확인하는 편이 빠릅니다. 서버에 접속할 수 있다면 워드프레스 설치 폴더에서 다음 한 줄로 현재 실행 중인 문서 루트를 그대로 출력할 수 있습니다.

<?php echo $_SERVER['DOCUMENT_ROOT'];

이 코드를 담은 파일을 임시로 올려 브라우저로 열어 보면, 웹서버가 그 도메인에 대해 어느 폴더를 루트로 쓰는지 즉시 알 수 있습니다. 확인이 끝나면 반드시 파일을 지워야 합니다.

응답 헤더 한 줄로 판별하기

서버 접속이 어렵다면 응답 헤더만으로도 상당 부분 판별됩니다. 터미널이나 개발자 도구의 네트워크 탭에서 상태 코드와 함께 X-Redirect-By 헤더가 있는지 보면 됩니다. 이 헤더에 워드프레스가 찍혀 있다면 그 요청은 워드프레스 내부에서 방향이 바뀐 것이고, 서버의 정적 파일 처리와는 무관합니다. 헤더가 아예 없고 서버 이름만 보인다면 웹서버 단계에서 끝난 요청입니다.

robots.txt와 sitemap.xml은 반대 함정이 있다

같은 루트 파일이라도 robots.txtsitemap.xml은 성격이 다릅니다. 이 둘은 파일이 없어도 워드프레스가 대신 만들어서 응답합니다. 그래서 404가 아니라 내용이 예상과 다른 형태로 문제가 드러납니다.

요청 경로 실제 파일이 있을 때 파일이 없을 때
/ads.txt 파일 내용 그대로 404
/robots.txt 파일 내용 그대로 워드프레스가 생성한 기본 내용
/sitemap.xml 파일 내용 그대로 코어 또는 플러그인이 생성

여기서 나오는 대표적인 혼란이 “플러그인에서 사이트맵 설정을 바꿨는데 반영되지 않는다”는 증상입니다. 원인은 대개 과거에 올려 둔 정적 sitemap.xml 파일이 루트에 남아 있는 것입니다. 앞에서 본 조건문 때문에 실제 파일이 언제나 이깁니다. 플러그인 설정을 아무리 바꿔도 그 파일을 지우기 전에는 화면이 바뀌지 않습니다.

robots.txt도 마찬가지입니다. 검색 설정에서 색인 관련 항목을 조정했는데 내용이 그대로라면, 파일이 실제로 존재하는지부터 확인해야 합니다. 반대로 파일이 없는데도 원하지 않는 차단 문구가 보인다면 그것은 워드프레스가 만든 가상 응답이므로, 파일을 찾을 것이 아니라 설정이나 필터를 봐야 합니다.

파일은 열리는데 검사 도구만 실패할 때

주소로 열면 내용이 정상으로 보이는데 외부 검사 도구만 계속 실패로 표시하는 경우가 있습니다. 이때는 눈에 보이지 않는 문자가 원인인 경우가 많습니다.

가장 대표적인 것이 파일 맨 앞에 붙는 바이트 순서 표시입니다. 윈도우 기본 메모장이나 일부 편집기는 UTF-8로 저장할 때 파일 첫머리에 사람 눈에 보이지 않는 세 바이트를 넣습니다. 브라우저는 이를 무시하고 내용을 그대로 보여 주지만, 첫 줄을 엄격하게 해석하는 검사기는 첫 줄 전체를 잘못된 줄로 처리합니다. 화면상으로는 완전히 정상인데 검증만 실패하는 전형적인 상황입니다.

해결은 간단합니다. 저장할 때 인코딩을 UTF-8로 지정하되 바이트 순서 표시를 넣지 않는 옵션을 고르면 됩니다. 편집기에 따라 표시가 다르므로, 확실하게 하려면 서버에서 새 파일로 다시 만드는 편이 빠릅니다.

확장자도 함께 봅니다. 윈도우 탐색기는 알려진 확장자를 숨기도록 기본 설정돼 있어서, 실제 이름이 두 번 겹친 상태인데 화면에는 정상으로 보일 수 있습니다. FTP 프로그램의 파일 목록에서 이름 전체가 그대로 나오는지 확인하는 것이 확실합니다.

멀티사이트에서는 파일 한 개를 여러 사이트가 나눠 쓴다

멀티사이트에서는 문제의 성격이 한 번 더 달라집니다. 서브디렉터리 방식이든 도메인 연결 방식이든, 여러 사이트가 같은 문서 루트 하나를 공유합니다. 사이트가 세 개여도 루트에 놓을 수 있는 ads.txt는 하나뿐입니다.

그래서 도메인마다 다른 승인 코드를 넣어야 하는 상황에서 정적 파일 방식은 애초에 성립하지 않습니다. 파일을 올리는 대신, 요청이 들어온 시점에 어느 사이트인지 판단해 내용을 만들어 내보내야 합니다. 다음은 mu-plugins 폴더에 두는 최소 형태입니다.

add_action('init', function () {
    if (strtok($_SERVER['REQUEST_URI'], '?') !== '/ads.txt') {
        return;
    }
    header('Content-Type: text/plain; charset=utf-8');
    echo get_option('my_ads_txt', '');
    exit;
});

사이트별 설정값을 읽어 출력하므로 도메인마다 다른 내용을 응답할 수 있습니다. 다만 이 방식이 동작하려면 루트에 같은 이름의 실제 파일이 없어야 합니다. 파일이 남아 있으면 요청이 워드프레스까지 오지 않아 코드가 실행되지 않습니다. 예전에 올려 둔 파일을 지우지 않은 채 코드를 넣고 “코드가 작동하지 않는다”고 판단하는 경우가 여기서 나옵니다.

실제 응답으로 확인한 결과

지금까지의 설명이 정말 그렇게 동작하는지, 도메인 두 개가 문서 루트 하나를 공유하는 멀티사이트에서 응답을 직접 받아 확인했습니다. 브라우저 화면이 아니라 응답 헤더와 본문을 그대로 본 결과입니다. 문서 루트에는 ads.txt, robots.txt, sitemap.xml 어느 것도 실제 파일로 존재하지 않는 상태였습니다.

요청 상태 Content-Type 본문
/ads.txt (도메인 A) 200 text/plain A의 게시자 정보
/ads.txt (도메인 B) 200 text/plain B의 다른 게시자 정보
/robots.txt 200 text/plain 워드프레스가 만든 기본 내용
/sitemap.xml 200 application/xml 생성된 XML
/no-such-file.txt 404 text/html 테마가 입혀진 완전한 HTML 문서

첫 두 줄이 멀티사이트의 핵심입니다. 파일은 하나도 없는데 도메인마다 다른 내용이 나옵니다. 정적 파일로는 만들 수 없는 응답이고, 요청 시점에 코드가 만들어 내보내고 있다는 증거입니다.

세 번째 줄이 앞에서 말한 반대 함정입니다. robots.txt는 파일이 없는데도 200으로 응답하고 내용까지 채워져 있습니다. 이 상태에서 루트에 파일을 하나 올리면 그때부터는 파일이 이깁니다. 설정을 바꿨는데 반영되지 않는다는 증상이 여기서 나옵니다.

마지막 줄이 404의 출처를 가리는 근거입니다. 없는 정적 파일을 요청했는데 Content-Typetext/plain이 아니라 text/html이고 본문이 완전한 HTML 문서로 돌아왔습니다. 웹서버가 만든 짧은 오류 문서가 아니라 워드프레스가 테마로 그린 404 페이지라는 뜻입니다. 요청이 PHP까지 들어갔다는 것이고, 곧 그 경로에 파일이 없다는 신고입니다.

헤더 한 줄로 갈라지는 지점

워드프레스가 개입했는지는 헤더에서 바로 드러납니다. 리디렉션이 일어나는 주소를 하나 요청해 보면 다음처럼 나옵니다.

HTTP/2 301
x-redirect-by: WordPress
location: https://example.com/130/

반면 정적 파일로 응답한 요청에는 이 헤더가 없고 server 헤더만 붙습니다. 그래서 파일이 열리지 않을 때 x-redirect-by가 보이면 워드프레스 내부에서 방향이 바뀐 것이고, 보이지 않으면서 404라면 웹서버 단계에서 끝난 요청입니다. 화면만 봐서는 구분되지 않는 두 상황이 헤더 한 줄로 갈립니다.

확인은 개발자 도구의 네트워크 탭에서 해당 요청을 클릭해 응답 헤더를 펼치면 됩니다. 상태 코드와 Content-Type, 그리고 x-redirect-by의 유무. 이 세 가지만 보면 지금까지 설명한 경우가 거의 다 구분됩니다.

파일도 맞고 코드도 맞는데 그대로일 때

마지막으로 확인할 계층은 캐시입니다. 정적 파일은 캐시 대상이 되기 쉽고, 404 응답 자체가 캐시되는 경우도 있습니다. 파일을 올리기 전에 접속한 기록이 있다면 그때의 404가 한동안 유지될 수 있습니다.

  • CDN을 쓰고 있다면 해당 경로만 캐시를 비웁니다.
  • 서버 단 캐시 플러그인이 있다면 전체 비우기를 한 번 실행합니다.
  • 브라우저는 시크릿 창으로 확인해 로컬 캐시를 배제합니다.
  • 확인은 www가 붙은 주소와 붙지 않은 주소 양쪽으로 각각 해 봅니다.

마지막 항목을 빠뜨리는 경우가 잦습니다. 두 주소가 서로 리디렉션으로 연결돼 있으면 검사 도구는 최종 도착지의 파일을 보게 되고, 반대로 각각 다른 설정을 가진 상태라면 한쪽에서만 파일이 보입니다.

권한도 함께 봅니다. 텍스트 파일은 소유자만 읽을 수 있는 권한으로 올라가면 웹서버가 읽지 못해 403이나 404로 이어집니다. 다른 정적 파일과 권한 값이 같은지 비교하는 것만으로도 대부분 걸러집니다.

확인 순서를 짧게 정리하면

1) 404 화면에 테마가 입혀져 있는지 본다 → 입혀져 있으면 파일이 그 경로에 없는 것이다.
2) 문서 루트를 직접 출력해 확인하고, 워드프레스 폴더가 아니라 그 자리에 파일을 둔다.
3) robots.txt·sitemap.xml은 반대로 남아 있는 옛 파일이 설정을 덮고 있지 않은지 본다.
4) 멀티사이트라면 파일이 아니라 코드로 응답을 만든다.
5) 그래도 그대로면 CDN·캐시·권한·www 유무를 차례로 확인한다.

이 순서를 지키면 퍼머링크 재저장이나 플러그인 비활성화처럼 원인과 관계없는 조치에 시간을 쓰지 않게 됩니다. 루트 파일이 열리지 않는 문제는 워드프레스 안쪽이 아니라 워드프레스에 도달하기 전 구간에서 결정되는 경우가 대부분이기 때문입니다.

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다