루트 도메인 이전 후 sitemap이 계속 옛날 도메인으로 뜨던 문제

블로그를 서브도메인(ts.world-currency.org)에서 루트 도메인(world-currency.org)으로 옮기는 작업을 하던 중, sitemap이 새 도메인으로 안 뜨는 문제를 겪었다. 원인이 한 겹이 아니라 세 겹으로 쌓여 있어서 정리해둔다.

증상

https://world-currency.org/sitemap_index.xml에 접속하면 응답은 정상적으로 오는데, 안에 있는 <loc> URL과 XSL 스타일시트 링크가 전부 옛날 서브도메인으로 찍혀 나왔다.
<?xml-stylesheet type="text/xsl" href="https://ts.world-currency.org/sitemap-stylesheet.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://ts.world-currency.org/post-type-post-sitemap-1.xml</loc>
    ...

브라우저로 열면 XSLT 스타일시트를 cross-origin으로 못 불러와서 빈 화면처럼 보이기도 했다.

원인 1: nginx가 엉뚱한 컨테이너로 프록시 중이었음

루트 도메인의 location /이 이미 안 쓰는 다른 컨테이너로 프록시되고 있었고, 그 컨테이너가 물고 있던 포트를 다른 서비스(워드프레스)가 재사용하고 있었다. 결과적으로 루트 도메인 요청이 의도치 않게 워드프레스 컨테이너로 흘러가는 상태였다.

docker ps --format "table {{.Names}}\t{{.Ports}}"

로 실제 포트 매핑을 확인하고, nginx의 proxy_pass를 워드프레스 컨테이너 포트로 맞춰줬다.

원인 2: 워드프레스가 DB에 저장된 도메인을 그대로 씀

워드프레스는 접속에 쓰인 Host 헤더가 아니라, wp_options 테이블의 siteurl/home 값을 “내 진짜 주소”로 기억하고 그걸 기준으로 모든 링크(sitemap 포함)를 생성한다. 이 값이 여전히 옛날 서브도메인으로 박혀 있었다.

UPDATE wp_options SET option_value = 'https://world-currency.org' WHERE option_name = 'siteurl';
UPDATE wp_options SET option_value = 'https://world-currency.org' WHERE option_name = 'home';

siteurl/home은 직렬화(serialize)된 배열이 아니라 단순 문자열이라, wp-cli의 search-replace 없이 SQL로 직접 바꿔도 안전했다. (참고로 wp-config.php에 WP_HOME/WP_SITEURL 상수가 하드코딩돼 있으면 DB값보다 우선 적용되니 같이 확인해야 한다.)

원인 3: SEO 플러그인이 sitemap을 파일로 캐시해두고 있었음

DB값을 바꿨는데도 sitemap 내용이 그대로였다. 알고 보니 SEO 플러그인(SureRank)이 sitemap 인덱스를 wp-content/uploads/.../sitemap/sitemap_index.json 같은 파일로 캐시해두는 구조였고, 도메인이 바뀌어도 자동으로 갱신되지 않았다.

[
    {
        "link": "https:\/\/ts.world-currency.org\/archives-sitemap-1.xml",
        "updated": "..."
    },
    ...
]

캐시 관련 DB 옵션(_sitemap_cache_checksum 류)을 지우거나 캐시 파일 자체를 삭제해도 자동으로 재생성되지 않았다. wp-cron을 강제로 돌려봐도 마찬가지였다. 결국 플러그인 관리자 화면에서 “Regenerate(재생성)” 버튼을 직접 눌러야 새 도메인 기준으로 다시 만들어졌다.

정리

  1. docker ps로 실제 포트 매핑 확인 후 nginx proxy_pass 정정
  2. wp_options의 siteurl/home을 새 도메인으로 UPDATE (wp-config.php 하드코딩 여부도 확인)
  3. SEO 플러그인 관리자 화면에서 sitemap “Regenerate” 버튼 클릭
  4. curl -H "Cache-Control: no-cache" <새 도메인>/sitemap_index.xml로 최종 확인

교훈

도메인을 옮길 때는 nginx 설정만으로 안 끝난다. 애플리케이션 자체가 자기 도메인을 어딘가(DB, 캐시 파일)에 기억하고 있는 경우가 많아서, “nginx → 앱 설정 → 캐시” 순으로 하나씩 확인해야 한다. 특히 SEO 플러그인의 sitemap은 실시간 생성이 아니라 캐시 기반인 경우가 흔하므로, 값만 바꾸고 캐시 무효화를 놓치면 계속 옛날 상태로 보인다.