Repo 의 모든 환경 변수가 부주의한 commit 한 번이면 public. Vite 의 env 모델은 일부러 보수적: 명시적 prefix, 레이어된 파일, 빌드 시 치환.
파일 계층
.env— 모든 모드에 로드. 비시크릿 디폴트엔 commit..env.local— 모든 모드에 로드, gitignored. 로컬 override..env.development— dev 에만 로드. Dev-안전 값 commit..env.production— build/preview 에만 로드..env.[mode].local— gitignored 모드-specific override.
Vite 가 순서대로 머지; 뒤 파일이 앞 거 override.
VITE_ prefix
VITE_ 로 시작하는 env var 만 import.meta.env.VITE_X 통해 클라이언트 코드에 inline. 다른 모든 것은 번들 밖 — 참조해도. 이건 정적 분석: prefix 가 본인 안전 레일.
빌드 시 치환
Vite 가 import.meta.env.VITE_X 를 빌드 시 실제 문자열로 교체. 변수 값이 JS 에 구워짐. 브라우저에 런타임 env lookup 없음. 두 결과:
- 값 변경에 rebuild 필요.
- 런타임만 의도한 시크릿 값은 절대 VITE_ prefix 쓰면 안 됨 — JS 에 있고 다운로드한 누구든 읽음.
런타임 config 는?
Rebuild 없이 배포마다 다른 config 필요하면 (멀티-테넌트, 지역-specific endpoint), 백엔드에서 런타임에 config fetch 또는 배포 시 HTML 통해 window.__APP_CONFIG__ 에 inject. Env var 는 빌드 시 디폴트용; 런타임 config 는 다른 문제.
클라이언트 번들에 있으면 public. 어떤 VITE_-prefixed 변수에도 DB URL, API 시크릿, auth 토큰 두지 마. JS 파일이 plaintext. 누구든 view-source.
Hey guys, if you're doing the exercise, the instructions are actually a bit misleading based on how Vite works.
The exercise says to use
.env.localand expects the production build to fall back to.env. But in Vite,.env.localoverrides EVERYTHING—both dev and build. So if you use.env.local, your production build will still end up with your localhost URL.To make it work the way the exercise actually wants you to, just do this:
Change the local filename from
.env.localto.env.development.localThis forces the localhost URL to only load during
npm run dev. Then when you runnpm run build, it'll properly switch over to the production URL in your.env.Save yourselves the headache and change the filename!