
| 구분 | 내용 |
|---|---|
| 프론트 | Vite로 빌드 → 결과물(dist)을 백엔드 서버에 업로드 |
| 배포 주소 | https://배포주소/admin (프론트 화면), https://배포주소/docs (백엔드 Swagger 같은 API Docs) |
| 백엔드 | 이미 HTTPS 적용되어 있음 |
| API 호출 | 프론트에서 http://api.domain.com 같은 주소로 호출 |
| 문제 | 프론트 화면은 HTTPS로 제공되는데, API는 HTTP로 호출 → Mixed Content 에러 발생 |
브라우저는 https:// 로 불러온 페이지에서 http:// 요청을 차단함.
Vite 빌드한 프론트엔드 코드에서 API Base URL이 http://api.domain.com 으로 설정되어 있었음.
결과적으로:
브라우저는 "야 HTTPS 페이지인데 왜 HTTP로 API를 부르냐" → Mixed Content 차단.
콘솔에 Mixed Content: The page at 'https://배포주소/admin' was loaded over HTTPS, but requested an insecure resource 'http://api.domain.com/endpoint'. This request has been blocked; the content must be served over HTTPS.
⇒ 근본적으로는 프론트 빌드 시 API BASE URL이 HTTP로 고정되어 있고 프론트용 배포 서버나 CICD구축이 되어있지 않는 상태에서 백엔드 경로 밑 /admin(엔드포인트만 다르게 설정)으로 빌드된 걸 배포함으로써 발생한 문제였다.
[🔶 Content-Security-Policy (CSP)의 upgrade-insecure-requests 디렉티브 활용]
<meta charset="UTF-8" http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"/>
HTTP → HTTPS 자동 업그레이드 명령으로 HTML의 로 설정하면, 서버가 아니라 클라이언트 쪽에서 강제로 바꿔준다.
Mixed Content를 CSP level에서 브라우저가 자동 보정해주는 방식"을 택해서 해결
코드 수정/배포 프로세스를 건드릴 수 없을 때 쓰는 응급처치지만, 표준 기술(CSP)로 서버가 HTTPS 대응만 되어 있다면 매우 유효한 해결법
[🔶 동작 예시]
[🔶 실무에서는 이걸 언제 써?]
[🔶 단점]
| 항목 | 내용 |
|---|---|
| 서버가 https 미지원이면 그대로 에러 | 서버가 https 대응 안 하면 Mixed Content 에러 대신 404 or 연결 실패 |
| 브라우저가 무조건 https로 바꾸기 때문에 예상치 못한 문제 가능 | 개발 환경이나 프록시에서 http만 되는 상황에서는 오히려 방해 |
| 클린 아키텍처 관점에서는 "핵심 코드 수정 없이 UI 메타로 우회"하는 꼼수 | 장기적으로는 환경변수, 빌드 프로세스 정비가 정답 |
+) 프론트 배포 시 BASE_URL을 app.mount 기준을 맞추는 이유
1. URL 경로가 꼬이기 때문
배포 시 프론트가 https://domain.com/admin/ 밑에 들어갈 때, vite base를 /admin/로 안 맞추면 빌드된 js, css가 루트(/) 기준으로 잡혀버린다.
base: '/':/admin/ 밑에 배포 시, base: '/admin/',로 설정해야 정확한 경로에서 요청을 할 수 있다.
2. app.mount와 배치 경로가 안 맞으면 SPA 라우팅도 꼬임
[🔶 app.mount와 base 경로의 관계]
| 항목 | 역할 |
|---|---|
| app.mount('#app') | index.html 내 특정 DOM element에 Vue App을 마운트 |
| base: '/admin/' | 빌드 시 정적 자원(js, css 등)의 경로를 /admin/ 기준으로 맞춤 |
| 둘 다 일치시키는 이유 | 실제 배포 경로(/admin)에 맞게 리소스 경로 + 라우팅 경로를 일관성 있게 유지 |