From 3017e7747970db7777715f495377424e4cf58bf1 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 18 May 2026 01:11:15 +0900 Subject: [PATCH] env: merge .env + .env.build instead of stopping at first match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer noted that returning on the first found file meant a project-root `.env.build` could shadow the dev `.env`, leaving the server without `PORT`/`HOST`/`SESSION_SECRET`. Switch `loadEnv()` to iterate every candidate with `override:false` so multiple files merge — first-loaded value wins per key. Order also reshuffled so dev's `.env` takes precedence over `.env.build` at the project root (server settings stay alive), while in packaged mode `resources/.env.build` still wins. Verified manually with a temp-dir reproduction. Co-Authored-By: Claude Opus 4.7 --- src/shared/env.ts | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/shared/env.ts b/src/shared/env.ts index 97c7c52..627de68 100644 --- a/src/shared/env.ts +++ b/src/shared/env.ts @@ -4,21 +4,27 @@ import dotenv from 'dotenv' import { projectRoot } from './paths.js' /** - * `.env` 를 읽어 `process.env` 에 주입. + * `.env` / `.env.build` 를 읽어 `process.env` 에 주입. * - * 탐색 순서(처음 발견된 것만 사용): - * 1. 패키징된 Electron 앱이면 `process.resourcesPath/.env.build` - * — electron-builder 의 extraResources 로 빌드 시점 `.env.build` 가 함께 - * 배포됨. 빌드용 도메인/설정을 dev `.env` 와 분리해 관리하기 위함. - * 2. 패키징된 Electron 앱이면 `process.resourcesPath/.env` - * — 운영자가 패키징 후 직접 `.env` 를 옆에 두고 덮어쓰는 경우를 대비한 폴백. - * 3. `<프로젝트 루트>/.env.build` - * — 개발 환경에서도 빌드용 값을 그대로 테스트하고 싶을 때. - * 4. `<프로젝트 루트>/.env` - * — 개발 실행(npm start / npm run installer*) 및 서버 운영용. + * 여러 파일을 순서대로 읽되 `override:false` 로 병합하므로 **먼저 로드된 값이 + * 우선**. 두 도메인(패키지 빌드용 vs 개발/서버용) 이 한 함수에서 자연스럽게 + * 분리됨: * - * - 이미 설정된 환경변수는 덮어쓰지 않음(쉘/systemd 에서 넘긴 값이 우선). - * - 파일이 없으면 조용히 통과. + * 1. 패키징된 Electron 앱: `process.resourcesPath/.env.build` + * — electron-builder 가 빌드 시점 `.env.build` 를 함께 배포. 패키지된 exe + * 에서 가장 먼저 적용되는 값. + * 2. 패키징된 Electron 앱: `process.resourcesPath/.env` + * — 운영자가 패키징 후 직접 `.env` 를 옆에 두고 덮어쓰는 경우 폴백. + * 3. `<프로젝트 루트>/.env` + * — 개발 실행(npm start / npm run installer*) 및 서버 운영용. 서버의 + * `PORT/HOST/SESSION_SECRET` 처럼 dev 에서 반드시 살아 있어야 하는 값들이 + * 있어, `.env.build` 보다 먼저 로드해 우선권을 줌. + * 4. `<프로젝트 루트>/.env.build` + * — dev 환경에서 빌드용 값(예: 운영 도메인 SITE_BASE_URL)을 테스트하고 + * 싶을 때 사용. `.env` 에 없는 키만 채움. + * + * - 이미 설정된 환경변수는 덮어쓰지 않음(쉘/systemd 에서 넘긴 값이 최우선). + * - 존재하지 않는 후보는 조용히 건너뜀. * - 서버/설치기/리소스팩설치기 진입점에서 한 번씩 호출. */ export function loadEnv(): void { @@ -28,13 +34,12 @@ export function loadEnv(): void { candidates.push(path.join(resourcesPath, '.env.build')) candidates.push(path.join(resourcesPath, '.env')) } - candidates.push(path.join(projectRoot, '.env.build')) candidates.push(path.join(projectRoot, '.env')) + candidates.push(path.join(projectRoot, '.env.build')) for (const envPath of candidates) { if (fs.existsSync(envPath)) { dotenv.config({ path: envPath, override: false, quiet: true }) - return } } }