C.W.K.
Stream
Lesson 03 of 07 · published

Env Modes — 시크릿 안 새는 .env 파일

~10 min · env, vite, modes, secrets

Level 0React 입문자
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
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.

Code

.env 파일 — 어디에 뭐 가는지·bash
# .env (committed) — 알아도 안전한 디폴트
VITE_APP_NAME=My App
VITE_API_URL=/api

# .env.local (gitignored) — 로컬 override
VITE_API_URL=http://localhost:8000

# .env.production (committed) — prod-only 안전 디폴트
VITE_API_URL=https://api.myapp.com

# .env.production.local (gitignored) — 배포-specific
VITE_SENTRY_DSN=https://...@sentry.io/...

# 서버 전용 시크릿 — VITE_ prefix 없음, 절대 어떤 클라이언트 번들에도 안 됨
DATABASE_URL=postgres://...
ADMIN_TOKEN=secret
코드에서 env var 읽기·tsx
// import.meta.env.VITE_X — string 타입 (또는 미설정 시 undefined).
const apiUrl: string = import.meta.env.VITE_API_URL;

// src/vite-env.d.ts 의 선언으로 타입-안전:
interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_APP_NAME: string;
  readonly VITE_SENTRY_DSN?: string;
}
interface ImportMeta {
  readonly env: ImportMetaEnv;
}

// 빌트인 모드:
const isDev = import.meta.env.DEV;       // dev 에서 true
const isProd = import.meta.env.PROD;     // build/preview 에서 true
const mode = import.meta.env.MODE;       // 'development' | 'production' | custom

External links

Exercise

Bootstrap 프로젝트에서: VITE_APP_NAMEVITE_API_URL 가진 .env 생성. 다른 VITE_API_URL 가진 .env.local 생성. import.meta.env 통해 App.tsx 에 둘 다 사용. Dev 가 .env.local 값 보여주는지, build 가 .env 값 보여주는지 확인. Non-VITE_ 변수 (SECRET=hi) 추가 시도 + 빌드된 번들에 안 나타나는지 확인 (grep dist/assets/).
Hint
dist/assets/*.js grep 이 VITE_ 값들 반환하지만 SECRET 절대 아님. SECRET 나타나면 어디선가 import.meta.env.SECRET 으로 참조 — Vite 의 정적 체크가 막았어야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.