Laravel을 Docker 기반의 Sail로 운영하고, Nginx를 호스트 서버(Ubuntu)에 리버스 프록시로 구성해 SSL을 적용했는데도, 브라우저에서 Mixed Content: HTTP 리소스를 요청했기 때문에 차단됨이라는 경고를 받았습니다.
빌드 결과에는 HTTPS가 잘 적용되어 있었는데, 도대체 왜 이런 문제가 발생했을까요?
💡 문제 상황 요약
- Laravel Sail은 Docker 컨테이너 내부에서 실행
- 호스트 서버는 Nginx를 설치해 SSL(HTTPS) 적용 및 리버스 프록시 설정
- vite.config.js에 base: 'https://도메인/build/' 명시하고, NODE_ENV=production으로 빌드도 완료
- public/build/manifest.json에도 http://는 없음
- 그럼에도 브라우저 HTML 출력에서는 모든 정적 자산 경로가 http://도메인/...으로 표시됨
- Laravel의 @vite() 혹은 Vite::prefetch()가 HTTP 링크를 출력하고 있었음
❗ 원인: Laravel이 HTTPS 요청을 HTTP로 인식하고 있었음
리버스 프록시 구조에서 Laravel은 실제로는 HTTPS 요청인데도 자체적으로는 HTTP 요청으로 인식합니다.
그래서 asset()이나 @vite() 같은 URL 생성기에서 http:// 경로를 만들고 있었던 것이죠.
이는 Laravel이 request()->isSecure() 를 기준으로 URL을 결정하기 때문입니다.
리버스 프록시를 사용할 경우, 이 값이 잘못 판단될 수 있습니다.
✅ 해결 방법: HTTPS 강제 인식 설정
Laravel의 AppServiceProvider에서 명시적으로 HTTPS를 강제 설정하면 문제는 즉시 해결됩니다.
app/Providers/AppServiceProvider.php
이 설정으로 Laravel은 request()->isSecure() 를 true로 인식하고,
모든 URL 생성기는 기본적으로 https://로 생성됩니다.
🔄 대안: Nginx에서 헤더 전달
Nginx 설정에서 아래 헤더를 Laravel로 넘기면 Laravel이 HTTPS 요청임을 더 정확히 판단할 수 있습니다.
그러나 이 경우 Laravel의 TrustProxies 미들웨어를 잘 설정해야 하며, Docker 환경에 따라 의도대로 동작하지 않는 경우가 있어
코드에서 직접 HTTPS를 강제하는 방식(URL::forceScheme)을 추천합니다.
🔒 Mixed Content 없이 안전한 서비스 제공!
이 설정 이후, 더 이상 "Mixed Content" 경고 없이 모든 정적 자산(JS, CSS, 이미지 등)이 https://로 잘 로드되었고,
Google Chrome의 보안 자물쇠도 다시 활성화되었습니다. 🎉
✅ 요약 정리
문제 | Laravel이 HTTPS 요청을 HTTP로 인식해 혼합 콘텐츠 오류 발생 |
환경 | Laravel Sail + Nginx 리버스 프록시 + Let's Encrypt |
핵심 해결 | URL::forceScheme('https') 로 HTTPS 강제 |
부가 설정 | proxy_set_header X-Forwarded-Proto https; |
Laravel 버전 | 9 이상, Vite 플러그인 사용 중 |
Laravel을 Docker로 운영 중이라면, 정적 자산 HTTPS 문제는 대부분 이 구조로 인해 발생하니 꼭 위 설정을 확인해보시기 바랍니다.
'개발 & IT > 백엔드' 카테고리의 다른 글
🚫 Nginx 413 Request Entity Too Large 오류 해결 방법 (0) | 2025.05.12 |
---|---|
Laravel 외래 키 삭제 처리 – onDelete() 옵션 정리 (1) | 2025.05.07 |
[SSH] 접속 오류 해결: “REMOTE HOST IDENTIFICATION HAS CHANGED!” 메시지가 떴을 때 (0) | 2025.04.30 |
MySQL에서 특수문자(①~⑩) 검색 및 제거하는 방법 (버전별 정리) (0) | 2025.04.04 |
Fail2Ban으로 리눅스 서버 보안 강화하기 (0) | 2025.02.12 |