본문으로 건너뛰기
개발 머꼬
개발 노트Node.js
hohyeon.dev39

dotenv를 지우고 Node 내장 --env-file로 옮기며 확인한 것들

  • #DevOps
  • #Engineering Note
  • #Node.js

문제 발생

스크립트마다 dotenv/config를 import하고 있었습니다. 의존성 하나를 줄이려고 Node 내장 기능으로 옮겼는데, CI에서 전부 죽었습니다.

Error: ENOENT: no such file or directory, open '.env'

CI에는 .env 파일이 없고 대신 job의 env: 블록으로 값을 주입하고 있었습니다.

원인 분석

두 플래그의 차이입니다. Node 문서가 --env-file을 이렇게 설명합니다 — 현재 디렉터리 기준의 파일에서 환경변수를 불러와 process.env로 제공하며, 파일이 존재하지 않으면 오류가 발생합니다.

그리고 그 바로 아래에 다른 플래그가 있습니다 — --env-file-if-exists는 동작은 같지만 파일이 없어도 오류를 던지지 않습니다.

우선순위 규칙도 중요합니다 — 같은 변수가 환경과 파일 양쪽에 정의되어 있으면 환경의 값이 우선합니다. CI가 env:로 넣은 값이 파일 때문에 덮어써지지 않는다는 뜻이라, 로컬 파일과 CI 주입을 함께 쓰는 구성이 안전합니다.

MEOKKO의 packages/db 스크립트들이 --env-file-if-exists=.env를 쓰는 이유가 정확히 이것입니다 — 로컬에는 파일이 있고, CI와 마이그레이션 Docker 이미지에는 없습니다.

해결 방안

  1. 없을 수도 있는 파일에는 -if-exists를 씁니다.
{ "scripts": { "db:migrate": "node --env-file-if-exists=.env ./migrate.ts" } }
  1. 여러 파일을 겹쳐 쓸 수 있습니다. 문서 설명대로 여러 개의 --env-file 인자를 넘길 수 있고, 뒤에 오는 파일이 앞 파일의 값을 덮어씁니다.
node --env-file=.env --env-file=.development.env index.js
  1. 지원되는 문법을 확인하고 옮깁니다. 문서에 명시된 것들입니다 — # 뒤는 주석, 값은 `·"·'로 감쌀 수 있고 따옴표는 값에서 제거되며, 여러 줄 값이 지원되고, 키 앞의 export 키워드는 무시됩니다. dotenv의 변수 확장(${OTHER}) 같은 기능은 없으므로 쓰고 있었다면 대안이 필요합니다.

  2. NODE_OPTIONS도 적용된다는 점을 인지합니다. 문서 그대로 Node.js를 설정하는 환경변수도 파싱되어 적용됩니다. 파일 한 줄이 런타임 동작을 바꿀 수 있습니다.

  3. .env는 여전히 커밋하지 않습니다. 로딩 방식이 바뀐 것이지 비밀 관리 방식이 바뀐 게 아닙니다. .env.example에는 이름과 placeholder만 둡니다.

  4. 런타임 버전을 확인합니다. --env-file은 v20.6.0, --env-file-if-exists는 v22.9.0에서 추가됐습니다 — 더 낮은 런타임을 쓰는 환경이 하나라도 있으면 조용히 실패합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.