최근 30분간 동시 방문자 수를 표시합니다. (~)
최고 동시 방문자 수 -
어제: 0명 / 오늘: 0명
1<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
upgrade-insecure-requests는 CSP(Content-Security-Policy)의 지시어(Directive)로, 웹 페이지 내의 모든 HTTP 요청(이미지, 스크립트, API 등)을 자동으로 HTTPS로 업그레이드하도록 브라우저에 지시합니다.
만약 HTTPS로 제공되는 웹 페이지에서 HTTP 리소스를 로드하면 XSS, MITM, 데이터 가로채기 등의 보안 취약점을 유발할 수 있으므로, 대부분의 브라우저에서는 이를 차단하거나 혼합 콘텐츠(Mixed Content) 경고를 발생시킵니다.
이때 HTTP 리소스 요청을 자동으로 HTTPS로 변환하면 혼합 콘텐츠 문제를 쉽게 해결할 수 있습니다.
개발 환경에서는 기본적으로 http://localhost:5173 같이 HTTP 주소를 사용합니다.upgrade-insecure-requests 지시어를 사용하면 이런 로컬 개발 서버도 HTTPS로 리다이렉트해야 하는데, Chrome이나 Firefox 등의 일반적인 브라우저는 예외 처리를 통해 HTTP 요청도 정상적으로 동작할 수 있습니다.
그런데 대표적으로 Safari 브라우저는 이런 예외 처리를 하지 않으며, 엄격하게 HTTP 요청을 HTTPS로 리다이렉트 시도합니다.
따라서 http://localhost 주소가 https://localhost로 리다이렉트 되면, HTTPS를 지원하지 않는 로컬 개발 서버로는 접근할 수 없게 됩니다.
이 문제를 해결하는 간단한 방법은 로컬 개발 환경에서는 Upgrade Insecure Requests 지시어를 사용하지 않도록 제거하는 것입니다.
지시어를 프로덕션 환경에서만 사용하도록 환경 변수 등을 활용해 조건부 적용합니다.
Vite 구성 예시
빌드 타임에 조건부로 CSP 메타 태그를 주입합니다.
1npm i -D vite-plugin-html
1234567891011121314151617181920import { defineConfig } from 'vite' import { createHtmlPlugin } from 'vite-plugin-html' const tags = [] if (process.env.NODE_ENV === 'development') { tags.push({ tag: 'meta', attrs: { httpEquiv: 'Content-Security-Policy', content: 'upgrade-insecure-requests' } }) } export default defineConfig({ plugins: [ createHtmlPlugin({ inject: { tags } }) ] })
Next.js 구성 예시
모든 경로 요청에 대해 CSP 헤더를 추가합니다.
123456789101112131415161718import type { NextConfig } from 'next' const nextConfig: NextConfig = { async headers() { return [ { source: '/:path*', headers: [ { key: 'Content-Security-Policy', value: process.env.NODE_ENV === 'production' ? 'upgrade-insecure-requests' : '' } ] } ] } } export default nextConfig
Sveltekit 구성 예시
애플리케이션에서 조건부로 CSP 메타 태그를 추가합니다.
1234567891011<script lang="ts"> import { dev } from '$app/environment' </script> <svelte:head> {#if !dev} <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" /> {/if} </svelte:head>
HTTPS 개발 서버 구성 예시
처음 로컬 Vite 개발 서버를 실행하면 비밀번호를 입력하라는 메시지가 표시될 수 있으며, 시스템 및 브라우저에 로컬 인증서가 설치됩니다.
이후로는 https://localhost으로 접근할 수 있습니다.
1npm i -D vite-plugin-mkcert
12345678import { defineConfig } from 'vite' import mkcert from 'vite-plugin-mkcert' export default defineConfig({ plugins: [ mkcert() ] })