SSL 인증서 적용 후 Mixed Content 경고 해결 방법 총정리

SSL 인증서를 적용했는데도 브라우저 주소창에 자물쇠 아이콘이 표시되지 않거나, 콘솔에 "Mixed Content" 경고가 출력된다면 HTTPS 페이지 내에서 HTTP 리소스를 참조하고 있기 때문입니다. 현대 브라우저는 보안상 이유로 스크립트, CSS, XHR 같은 활성 혼합 콘텐츠를 기본 차단하며, 이미지나 비디오 같은 수동적 콘텐츠도 경고를 표시합니다. 이 글에서는 혼합 콘텐츠의 원인을 정확히 진단하고, 프론트엔드와 서버 양쪽에서 즉시 적용 가능한 해결 방법을 제시합니다.


SSL인증서적용후MixedContent경고해결방법총정리


1. 혼합 콘텐츠(Mixed Content)란 무엇인가

혼합 콘텐츠는 HTTPS로 로드된 페이지에서 HTTP 프로토콜로 외부 리소스를 불러오는 상황을 의미합니다. 브라우저는 이를 두 가지 유형으로 분류합니다.

  • 활성(Active) 혼합 콘텐츠: JavaScript, CSS, iframe, XHR, Fetch 등 페이지의 동작과 레이아웃을 변경할 수 있는 리소스. Chrome, Firefox, Edge, Safari 모두 기본적으로 차단합니다.
  • 수동적(Passive) 혼합 콘텐츠: 이미지, 오디오, 비디오 등 페이지의 핵심 동작에 영향을 주지 않는 리소스. 경고와 함께 로드될 수 있으나 보안 경고가 표시됩니다.

이 문제를 방치하면 사용자의 개인정보가 중간자 공격(MITM)에 노출될 수 있으며, SEO 점수 하락과 신뢰도 저하로 이어집니다. 특히 Google은 HTTPS를 검색 순위 요소로 반영하고 있으므로, 혼합 콘텐츠 해결은 선택이 아닌 필수입니다.

2. 혼합 콘텐츠의 주요 원인 4가지

문제를 해결하려면 먼저 원인을 정확히 파악해야 합니다. 실무에서 자주 마주치는 케이스는 다음과 같습니다.

  1. 하드코딩된 HTTP URL: 소스 코드 내에 http://api.example.com 형태로 직접 작성된 경우
  2. 상대 URL의 프로토콜 문제: src="/assets/image.png"는 정상이지만, src="//cdn.example.com/image.png"가 HTTP 기본 프로토콜을 참조하는 경우
  3. 레거시 코드 및 서드파티 라이브러리: 오래된 jQuery 플러그인이나 외부 위젯이 HTTP 리소스를 참조
  4. CMS/DB에 저장된 URL: WordPress, Django Admin 등에서 게시물 작성 시 업로드한 이미지 경로가 HTTP로 저장된 경우

진단 팁: Chrome DevTools를 열고(F12) Console 탭에서 "Mixed Content"를 검색하면 차단된 리소스 목록이 표시됩니다. Network 탭에서 Protocol 컬럼을 확인하여 HTTP 요청을 필터링할 수도 있습니다.

3. 프론트엔드 해결 방법 (코드 레벨)

소스 코드에서 HTTP 참조를 제거하는 것이 가장 확실한 방법입니다. 다음 순서로 점검하십시오.

3-1. 프로토콜 상대 URL로 변경

리소스가 HTTPS를 지원한다면, 프로토콜을 생략한 상대 URL을 사용할 수 있습니다.

// 변경 전
const apiUrl = 'http://api.example.com/data';

// 변경 후
const apiUrl = '//api.example.com/data';

주의: 이 방식은 외부 서버가 HTTPS를 지원할 때만 작동합니다. 그렇지 않으면 여전히 HTTP로 요청되므로, 가능하면 명시적으로 https://를 사용하는 것을 권장합니다.

3-2. 코드베이스 전체 검색 및 치환

  • VS Code, IntelliJ 등 IDE에서 http://를 전체 검색(Ctrl+Shift+F)하여 하드코딩된 URL을 모두 찾아냅니다.
  • img src=, script src=, link href=, fetch(, XMLHttpRequest 등 리소스 로드 구문을 중점 검토합니다.
  • 정규표현식을 활용한 일괄 치환: http://https://

3-3. 서드파티 라이브러리 업데이트

jQuery, Bootstrap, Google Fonts 등 외부 CDN 참조가 HTTP인 경우, 최신 버전으로 교체하거나 공식 HTTPS CDN 주소로 변경합니다. npm/yarn 의존성도 npm outdated로 점검 후 업데이트하십시오.

4. 서버 측 해결 방법 (헤더 설정)

코드 수정만으로 해결이 어렵다면, 서버 응답 헤더를 통해 브라우저에게 자동 업그레이드를 지시할 수 있습니다.

4-1. Content-Security-Policy: upgrade-insecure-requests

이 헤더를 설정하면 브라우저가 모든 HTTP 요청을 자동으로 HTTPS로 변환합니다.

// Node.js + Helmet 예시
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
  directives: {
    upgradeInsecureRequests: []
  }
}));

Nginx 설정 예시:

add_header Content-Security-Policy "upgrade-insecure-requests";

실무 팁: 이 헤더는 외부 리소스가 HTTPS를 지원하지 않으면 로드 실패로 이어지므로, 반드시 사전 테스트 후 적용해야 합니다.

4-2. Strict-Transport-Security (HSTS) 적용

HSTS는 브라우저에게 "이 사이트는 항상 HTTPS로만 접속하라"고 강제하는 헤더입니다.

// Node.js + Helmet
app.use(helmet.hsts({
  maxAge: 63072000, // 2년
  includeSubDomains: true,
  preload: true
}));

Nginx 설정:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

주의: HSTS preload 리스트에 등록하면 브라우저가 영구적으로 HTTPS만 허용하므로, 롤백이 불가능합니다. 충분한 테스트 후 적용하십시오.

4-3. CMS/DB 저장 URL 일괄 수정

WordPress의 경우 phpMyAdmin이나 WP-CLI로 DB 내 URL을 일괄 변경할 수 있습니다.

# WP-CLI 예시
wp search-replace 'http://example.com' 'https://example.com' --dry-run
wp search-replace 'http://example.com' 'https://example.com'

Django나 Rails 등 다른 프레임워크도 마이그레이션 스크립트를 작성하여 DB 레코드를 일괄 업데이트할 수 있습니다.

5. 테스트 및 검증 방법

수정 후 반드시 다음 절차로 검증하십시오.

  • Chrome DevTools Console: Mixed Content 경고가 사라졌는지 확인
  • Network 탭: Protocol 컬럼에서 모든 요청이 h2 또는 https로 표시되는지 점검
  • 주소창 자물쇠 아이콘: 클릭 시 "연결이 안전함" 메시지 확인
  • SSL Labs: https://www.ssllabs.com/ssltest/에서 A+ 등급 획득 여부 검증

임시 디버깅 팁: Chrome 주소창의 자물쇠 아이콘 → 사이트 설정 → "안전하지 않은 콘텐츠"를 "허용"으로 변경하면 차단된 리소스를 일시적으로 로드하여 원인을 파악할 수 있습니다. 단, 이는 개발 환경에서만 사용하고 프로덕션에서는 절대 권장하지 않습니다.

6. 정리 및 Action Item

혼합 콘텐츠는 HTTPS 페이지에서 HTTP 리소스를 참조하여 발생하며, 브라우저는 활성 콘텐츠를 차단하고 수동적 콘텐츠는 경고와 함께 표시합니다. 해결 방법은 크게 두 가지로 나뉩니다. 첫째, 프론트엔드 코드에서 모든 HTTP URL을 HTTPS로 변경하거나 프로토콜 상대 URL을 사용하고, 서드파티 라이브러리를 업데이트합니다. 둘째, 서버에서 Content-Security-Policy: upgrade-insecure-requests와 HSTS 헤더를 설정하여 브라우저가 자동으로 HTTPS를 사용하도록 강제합니다.

당장 실행할 Action Item: Chrome DevTools Console을 열고(F12) "Mixed Content"를 검색하여 차단된 리소스 목록을 확보한 뒤, 해당 URL을 HTTPS로 변경하거나 CSP 헤더를 적용하십시오. 이 두 가지만 완료해도 대부분의 혼합 콘텐츠 문제는 해결됩니다.





# 함께 보면 좋은 글

댓글