콘텐츠로 건너뛰기

[블로그운영] 워드프레스 이미지가 안 보일 때 mixed content 해결하는 법

  • 기준

블로그 이미지 하나가 갑자기 안 뜹니다. 미디어 라이브러리에는 멀쩡히 있습니다. 파일도 서버에 그대로 있습니다. 그런데 화면에서는 깨진 아이콘만 보입니다.

정리하는 개발자 워니즈입니다. 이 글에서는 이 mixed content 증상의 원인을 찾는 순서와, wp-config.php 한 줄을 고쳐서 끝내는 방법을 다룹니다.

결론부터 말씀드리면 파일 문제가 아니라 주소 문제이고, 정확한 이름은 mixed content 차단입니다. 이미지 주소가 http로 저장돼 있으면, https 페이지에서는 브라우저가 아예 차단합니다. 개발자도구 콘솔에 mixed content 경고가 있는지부터 확인하세요.

워드프레스 mixed content 진단 — 증상, 원인, 해결

왜 이게 문제인가

브라우저는 https 페이지 안에서 http 리소스를 불러오는 것을 보안 위협으로 봅니다. 중간에서 내용을 바꿔치기할 수 있기 때문입니다. 그래서 요청을 보내지도 않고 차단합니다.

여기서 사람을 헷갈리게 만드는 지점이 있습니다. 서버에 http를 https로 보내는 리다이렉트를 걸어두면 해결될 것 같지만 안 됩니다. 차단이 요청 전에 일어나기 때문에 리다이렉트까지 갈 일이 없습니다. 주소창에 이미지 주소를 직접 붙여넣으면 잘 열리는데 페이지 안에서만 안 보이는 이유가 이것입니다.

1. mixed content인지부터 확인

깨진 이미지에서 마우스 오른쪽 버튼을 눌러 이미지 주소를 복사한 뒤, 새 탭에 그대로 붙여넣어 봅니다.

  • 이미지가 잘 뜬다 → 파일은 멀쩡합니다. 주소 문제입니다.
  • 404가 뜬다 → 이 글의 경우가 아닙니다. 파일 유실 쪽을 보셔야 합니다.

주소가 잘 열린다면 F12를 눌러 콘솔을 확인합니다.

Mixed Content: The page at 'https://example.com/' was loaded over HTTPS,
but requested an insecure element 'http://example.com/wp-content/uploads/...'.
This request has been blocked.

이 경고가 보이면 원인이 확정된 것입니다. 차단 규칙 자체는 MDN의 mixed content 문서에 정리돼 있습니다.

2. mixed content를 만드는 설정 한 줄 찾기

워드프레스 루트의 wp-config.php를 엽니다. 도커나 비트나미 같은 이미지로 설치했다면 이런 줄이 들어 있는 경우가 많습니다.

define( 'WP_HOME', 'http://' . $_SERVER['HTTP_HOST'] . '/' );
define( 'WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] . '/' );

문제가 두 가지 겹쳐 있습니다.

첫째, 앞에 http가 박혀 있습니다. https로 접속해도 워드프레스는 자기 주소를 http로 인식합니다.

둘째, $_SERVER['HTTP_HOST']는 접속한 사람이 입력한 주소를 그대로 가져옵니다. 도메인으로 들어오면 도메인이, IP로 들어오면 IP가 들어갑니다. 그 상태에서 글을 쓰거나 이미지를 올리면 그때 접속했던 주소가 DB에 그대로 굳습니다.

제 경우 DB를 열어보니 도메인 두 개와 서버 IP까지 섞여 있었습니다. 어느 경로로 접속해서 작업했느냐에 따라 다르게 저장된 것입니다.

3. 고정 주소로 바꾸기

두 줄을 실제 도메인으로 못박습니다.

define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com' );

수정 전에 백업부터 뜹니다.

cp wp-config.php wp-config.php.bak

저장한 뒤 웹서버를 다시 시작합니다. PHP-FPM을 쓴다면 그쪽도 같이 재시작해야 반영됩니다.

sudo systemctl restart php-fpm nginx

4. 이미 저장된 주소 정리

설정을 고쳐도 이미 DB에 http로 저장된 주소는 그대로 남아 있습니다. 과거 글의 이미지는 여전히 깨집니다.

WP-CLI가 있다면 한 줄로 끝납니다. --dry-run으로 몇 건이 바뀌는지 먼저 보는 편이 안전합니다.

wp search-replace 'http://example.com' 'https://example.com' --all-tables --dry-run
wp search-replace 'http://example.com' 'https://example.com' --all-tables

IP 주소로 저장된 것도 있다면 같은 방식으로 한 번 더 돌립니다. 아래 SERVER_IP 자리에 실제 값을 넣으시면 됩니다.

wp search-replace 'http://SERVER_IP' 'https://example.com' --all-tables

WP-CLI가 없다면 Better Search Replace 같은 플러그인으로 같은 작업을 할 수 있습니다. 어느 쪽이든 DB 백업을 먼저 받으세요. 직렬화된 데이터가 들어 있는 테이블은 단순 SQL로 치환하면 깨질 수 있습니다.

5. 덤으로 따라오는 효과

주소를 도메인으로 고정하면 부수적으로 하나가 더 정리됩니다. IP로 저장돼 있던 주소들이 사라지면서 페이지 소스에 서버 IP가 노출되던 것도 같이 없어집니다.

원래 이런 흔적은 잘 보이지 않습니다. 브라우저에서 소스 보기를 한 뒤 숫자로 된 주소가 남아 있는지 한 번 검색해 보시면 확인됩니다. 공격자가 가장 먼저 찾는 정보라 안 남기는 편이 낫습니다. 서버를 직접 굴리면서 겪은 다른 이야기는 블로그 서버 비용을 0원으로 만든 방법에 적어뒀습니다.

mixed content 관련해 자주 묻는 것

Q. SSL 인증서를 방금 붙였는데 이미지만 안 나옵니다.<br>가장 흔한 경우입니다. 인증서를 붙이기 전에 쓴 글의 이미지 주소가 전부 http로 저장돼 있기 때문입니다. 4번 항목의 치환을 돌리면 해결됩니다.

Q. 플러그인으로 강제 https 처리하면 안 되나요?<br>당장은 됩니다. 다만 출력 시점에 주소를 바꿔치기하는 방식이라 DB에는 http가 그대로 남습니다. 플러그인을 끄면 증상이 돌아오고, 피드나 API 응답처럼 필터를 안 타는 곳에서는 여전히 http가 나갑니다. 근본 해결은 아닙니다.

Q. 일부 이미지만 깨지는 이유는 뭔가요?<br>접속 경로에 따라 저장된 주소가 달랐기 때문입니다. 도메인으로 접속해 올린 이미지는 정상이고, IP로 접속해 올린 이미지만 깨지는 식입니다. 규칙성이 없어 보이는 이유가 이것입니다.

정리

  • 이미지 주소를 새 탭에서 열어봅니다. 열리면 파일이 아니라 주소 문제입니다.
  • 콘솔의 mixed content 경고로 원인을 확정합니다.
  • wp-config.phpWP_HOMEWP_SITEURL을 https 도메인으로 고정합니다.
  • 이미 저장된 주소는 wp search-replace로 치환합니다. 백업이 먼저입니다.
  • 서버 IP가 소스에 남아 있었다면 같이 정리됩니다.

오늘 하나만 하신다면, 개발자도구 콘솔을 열고 mixed content로 검색해 보세요. 경고가 하나라도 잡히면 위 순서를 그대로 따라가시면 됩니다.

답글 남기기

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