빠른 설정
// Node.js 20.6+ — dotenv 없이 .env 직접 로드
// node --env-file=.env server.js
const port = Number(process.env.PORT ?? 3000);
const debug = process.env.DEBUG === "true";
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) throw new Error("DATABASE_URL is required");
if (!Number.isInteger(port)) throw new Error("PORT must be an integer");
export const config = { port, debug, dbUrl };설정 경계
먼저 구분해 둘 기본형은 아래입니다.
- 문자열 입력 읽기:
process.env.PORT - 부트 단계 변환:
Number(...),=== "true" - 필수값 검증:
if (!value) throw ... - 앱 내부 설정 객체:
const config = { ... } - env 파일 로드:
node --env-file=.env
.env는 입력 경로이고, 앱 설정 객체는 별도여야 한다
환경 변수 파일과 애플리케이션 설정은 같은 개념이 아닙니다. .env는 문자열 입력이고, 실제 앱은 타입이 정리된 config 객체를 써야 합니다.
--env-file은 여러 번 줄 수 있고, 같은 키가 실제 환경 변수와 파일 양쪽에 있으면 실제 환경 변수가 우선합니다.
process.env는 시작 시 한 번만 읽는 편이 낫다
코드 곳곳에서 직접 읽기 시작하면 누락, 오타, 타입 변환 실수가 요청 처리 중간에서 터집니다. 부트 단계에서 읽고 검증하고 고정하는 편이 운영상 훨씬 낫습니다.
모든 값은 문자열로 들어온다
포트, 불리언, CSV 목록 같은 값은 직접 변환해야 합니다. 여기서는 dotenv 문법보다 "타입 변환과 검증을 어디서 하느냐"가 핵심입니다.
필수값, 선택값, 빈 문자열을 구분한다
설정 검증에서 자주 놓치는 부분은 "없음"과 "비어 있음"을 같은 것으로 처리하는 지점입니다.
비밀번호, URL, 토큰처럼 비어 있으면 안 되는 값은 undefined뿐 아니라 ""도 실패로 보는 편이 보통 맞습니다.
시크릿과 일반 설정을 같이 다루지 않는다
로컬 개발용 .env는 편하지만, 운영 시크릿은 저장소나 이미지에 남기지 않는 경로가 더 안전합니다. .env.example은 키 구조 공유용이고, 실제 값 파일은 배포 자산이 아닙니다.
설정 소스가 여러 개면 우선순위를 코드로 고정한다
env 파일, 실제 환경 변수, CLI 인자, 기본값이 섞이면 "어느 값이 마지막으로 이기는가"를 눈으로 추적하기 어려워집니다.
실전에서는 load 순서와 override 규칙을 loadConfig() 안에서 한 번에 고정하는 편이 좋습니다.
어디에 둘까
체크포인트
.env로드:node --env-file=.env- 여러 env 파일을 순서대로 로드할 수 있음
- 문자열 -> 숫자:
Number(...) - 문자열 -> 불리언:
=== "true" - 필수값과 빈 문자열을 구분해서 검증
- 설정 경계:
loadConfig()한 곳에서 검증 - 운영 시크릿: 런타임 주입 또는 시크릿 매니저
- env 파일, 실제 env, CLI 인자 우선순위를 코드로 고정
주의할 점
설정 누락을 요청 처리 중간에서 발견하면 이미 늦다. 환경 변수는 부트 단계에서 검증하고, 실패하면 서버를 바로 죽이는 편이 맞다.
참고 링크
2 sources