Electron 앱을 개발하다가 .env
파일로 API 주소 같은 환경변수를 넣고 싶어서 이렇게 작성했어요.
// main.ts
import * as dotenv from 'dotenv';
dotenv.config();
console.log(process.env.VITE_API_BASE_URL1); // ❌ undefined
Node 환경에서 이 방식은 너무 당연하잖아요?
그런데 Electron에서는… 왜 이게 안 될까요?
Electron의 메인 프로세스(Main Process)는 실제로 Node.js 런타임 위에서 실행됩니다.
fs
, child_process
, path
같은 Node 내장 모듈도 자유롭게 사용할 수 있고,
console.log(process.platform)
도 잘 찍혀요.
그래서 대부분의 개발자(저 포함)는 이렇게 생각합니다:
“Node 환경이니까 .env + dotenv + process.env 조합이면 당연히 환경변수 잘 들어오겠지!”
이 생각, 틀린 건 아니에요. Electron은 분명 Node 기반이니까요.
그런데 여기서 하나 간과한 게 있었습니다.
Electron 프로젝트를 만들 때 Vite를 사용하는 경우가 많습니다.
렌더링 속도 빠르고, 설정 간단하고, React 기반 UI까지 바로 통합되니까요.
그런데…
즉, 우리가 작성한 코드를 실행하는 게 아니라,
미리 빌드해서 정적인 결과물로 만들어주는 도구라는 점입니다.
이건 메인 프로세스(main.ts
)도 예외가 아닙니다.
우리가 Vite로 메인도 같이 번들링하면,
그 순간부터는 Node 런타임에 의한 실행이 아니라
Vite가 만들어낸 JS 결과물의 실행이 되는 거예요.
process.env
를 무시할까?Vite는 빠른 개발환경과 빌드 성능을 위해 정적 분석(static analysis) 기반으로 작동합니다.
그래서 “코드 안에서 예측 가능한 부분만” 치환해줍니다.
process.env.XXX
는 런타임에 정해지는 값이라
Vite 입장에선 “이 값이 뭔지 미리 모른다” → 아예 무시!
반면 import.meta.env.VITE_XXX
는
Vite가 .env
파일을 빌드 타임에 읽어서 코드에 직접 박아 넣어줄 수 있는 "정적인 값"입니다.
// 개발자가 작성한 코드
const apiUrl = import.meta.env.VITE_API_BASE_URL1;
⬇ 빌드 후
const apiUrl = "https://api.example.com"; // 정적 치환됨!
반면 이런 건?
console.log(process.env.VITE_API_BASE_URL1);
⬇ 빌드 후에도 여전히
console.log(process.env.VITE_API_BASE_URL1); // undefined
아무 처리도 되지 않은 채 남아 있다가,
실행 시에도 .env
를 읽지 않으니 undefined
가 되는 거죠.
process.env
가 작동했던 거예요?여기서 많은 개발자가 헷갈립니다.
개발 모드에서는 Vite dev server가 Node 기반으로 돌아가고,
일부 경우 process.env
값이 들어가는 것처럼 보일 수 있어요.
이건 사실 Vite가 define
속성이나 dotenv
로딩을 통해 임시로 넣어준 값일 뿐,
"우연히" 동작하는 것일 뿐입니다.
✅ 개발 모드에서는 동작할 수도 있음
❌ 하지만 빌드 모드에서는 100% 무시됩니다
❓질문 | ✅흔한 생각 | ❌실제 동작 |
---|---|---|
Electron 메인은 Node 환경이니까 process.env 되겠지? | 맞는 말처럼 보임 | Vite 빌드 시엔 무시됨 |
dotenv 쓰면 .env 읽지 않나요? | Node에서는 맞음 | Vite는 무시함 |
.env 만 바꾸면 반영되나요? | 될 것 같지만 | 반드시 재빌드 필요 |
항목 | Node.js (process.env ) | Vite (import.meta.env ) |
---|---|---|
처리 시점 | 런타임 | 빌드타임 |
방식 | dotenv 등으로 .env 읽음 | Vite가 직접 코드에 값 치환 |
유연성 | .env 만 바꿔도 바로 반영 | .env 바꾸면 반드시 재빌드 |
보안 제어 | 제한 없음 | VITE_ 접두사로 제한 |
주 사용처 | 백엔드, CLI, 서버 | 프론트엔드, Electron, SPA 앱 등 |
위치 | 환경변수 접근법 | 설명 |
---|---|---|
렌더러 (React 등) | import.meta.env.VITE_XXX | ✅ Vite가 치환 |
메인 프로세스 (main.ts) | import.meta.env.VITE_XXX | ✅ 마찬가지로 Vite가 치환 |
process.env 사용 | ❌ Vite 빌드 시 무시됨 | undefined 위험 있음 |
.env
만 바꾸면 바로 적용되나요? ❌ 아니요!Vite는 빌드 타임에 .env
파일을 읽어서 코드를 바꾸기 때문에,
.env
변경 후에는 반드시 vite build
같은 빌드 작업을 다시 해야 반영됩니다.
Electron 메인은 Node 환경이다 → process.env 가능
BUT Vite로 빌드하면 정적 분석 기반 → process.env 무시됨
→ import.meta.env.VITE_XXX 만 써야 함!
Vite를 사용하는 순간, "런타임의 유연성"보다
"빌드 시점의 확정성과 정적 최적화"가 더 중요해집니다.
이 차이를 이해하는 것이 Electron + Vite 개발의 핵심이에요.