</>DevTools

ENV.env 파서

.env 파일 파싱 및 편집

.env 파일 문법과 환경변수를 다룰 때 알아야 할 것들

.env 파일은 KEY=value 를 한 줄에 하나씩 적는 단순한 형식입니다. 그런데 이 '단순함'을 규정하는 공식 표준이 없어서, 따옴표 처리나 줄바꿈 같은 세부 동작이 라이브러리마다 다릅니다. 이 도구는 붙여넣은 .env 내용을 키-값으로 분해해 보여 주므로, 파서가 실제로 무엇을 읽어 들이는지 확인할 수 있습니다.

기본 문법

키는 관례적으로 대문자와 밑줄만 씁니다. 셸에서 환경변수로 export될 수 있어야 하기 때문이며, 하이픈이 들어간 키는 셸에서 다룰 수 없습니다. 등호 주변에 공백을 넣는 것도 피하세요. KEY = value 로 쓰면 파서에 따라 키가 "KEY "가 되거나 값이 " value"가 됩니다.

일반적인 .env 파일
# 주석은 # 으로 시작
NODE_ENV=production
PORT=3000

# 값에 공백이 있으면 따옴표
APP_NAME="My Application"

# 빈 값도 유효
OPTIONAL_FLAG=

# URL처럼 특수문자가 많은 값
DATABASE_URL=postgres://user:pass@localhost:5432/mydb

# 여러 줄 값 (지원하는 파서에서만)
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBg...
-----END PRIVATE KEY-----"

사용 방법

  1. .env 파일 내용을 붙여넣습니다.
  2. 파싱된 키-값 목록을 확인합니다. 의도한 값이 정확히 들어갔는지, 따옴표가 값에 포함되지 않았는지 봅니다.
  3. 값이 잘려 있다면 아래의 따옴표·특수문자 항목을 확인하세요.
  4. 결과를 코드나 배포 설정 화면에 옮겨 씁니다.

따옴표가 필요한 경우와 그 부작용

실무에서 가장 자주 겪는 사고가 비밀번호에 들어간 $ 와 # 입니다. 일부 파서는 $VAR 를 다른 환경변수 참조로 확장하고, # 이후를 주석으로 버립니다. 그 결과 비밀번호가 조용히 잘려서 인증 실패로 나타나는데, 로그에는 비밀번호를 찍지 않으니 원인 파악이 오래 걸립니다. 특수문자가 포함된 값은 작은따옴표로 감싸는 것이 가장 안전합니다.

작성 방식파싱 결과비고
KEY=hellohello가장 단순한 형태
KEY="hello world"hello world따옴표는 제거됨
KEY=hello worldhello world 또는 hello파서에 따라 다름 — 따옴표를 쓰세요
KEY="line1\nline2"줄바꿈이 포함된 값큰따옴표에서만 \n 해석
KEY='line1\nline2'문자 그대로 line1\nline2작은따옴표는 이스케이프 미해석
KEY=value # 주석value 또는 value # 주석인라인 주석 지원 여부가 다름
KEY=pa$$wordpa 또는 pa$$word$ 는 변수 확장으로 해석될 수 있음

환경변수는 문자열뿐이다

운영체제 수준에서 환경변수의 값은 항상 문자열입니다. 여기서 흔한 버그가 나옵니다. DEBUG=false 로 설정해도 process.env.DEBUG 는 문자열 "false" 이고, JavaScript에서 비어 있지 않은 문자열은 참이므로 if (process.env.DEBUG) 는 통과합니다. 숫자도 마찬가지로 PORT=3000 은 "3000" 이어서 산술 연산에서 문자열 연결이 일어납니다.

그래서 환경변수는 읽는 즉시 한 곳에서 검증하고 변환하는 패턴이 권장됩니다. zod나 envalid 같은 라이브러리로 스키마를 정의하면, 필수 값이 빠졌을 때 애플리케이션이 시작 시점에 명확한 오류로 죽습니다. 런타임 중간에 undefined로 이상하게 동작하는 것보다 훨씬 낫습니다.

시작 시점 검증 패턴
import { z } from "zod";

const env = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]),
  PORT: z.coerce.number().default(3000),
  DEBUG: z.stringbool().default(false),
  DATABASE_URL: z.string().url(),
}).parse(process.env);

// 이후 코드에서는 env.PORT 가 실제 number
export default env;

우선순위와 파일 분리

대부분의 라이브러리는 이미 설정된 실제 환경변수를 .env 파일 값으로 덮어쓰지 않습니다. 즉 셸에서 export한 값이나 컨테이너에 주입된 값이 이깁니다. 이는 의도된 설계입니다. 배포 환경에서는 플랫폼이 주입한 값이 파일보다 우선해야 하기 때문입니다.

여러 파일을 쓰는 관례도 있습니다. .env 는 공통 기본값, .env.local 은 개인 로컬 설정(커밋 제외), .env.production 은 환경별 값입니다. Next.js나 Vite 같은 도구는 이 순서를 정해 두고 로드하므로, 값이 예상과 다르면 어느 파일이 최종적으로 이겼는지 확인해야 합니다.

보안에서 반드시 지킬 것

  • .env 를 .gitignore 에 넣습니다. 대신 .env.example 에 키 이름만 적고 값은 비워 두어 팀이 필요한 항목을 알 수 있게 합니다.
  • 이미 커밋했다면 히스토리에서 지우는 것으로 끝내지 마세요. 노출된 자격증명은 즉시 교체해야 합니다. 저장소가 공개였다면 이미 자동 스캐너에 수집되었다고 가정하는 편이 안전합니다.
  • 클라이언트에 노출되는 변수를 구분하세요. Next.js의 NEXT_PUBLIC_, Vite의 VITE_ 접두사가 붙은 값은 브라우저 번들에 그대로 포함됩니다. 이 접두사를 붙인 변수에 비밀값을 넣으면 그 즉시 공개됩니다.
  • 운영 환경의 비밀값은 파일보다 시크릿 매니저(AWS Secrets Manager, GCP Secret Manager, Vault)에 두는 것이 안전합니다. 접근 감사와 교체가 가능해집니다.
  • CI 로그에 환경변수를 덤프하지 마세요. env 나 printenv 출력이 로그에 남으면 로그 접근 권한이 있는 모두에게 노출됩니다.

자주 묻는 질문

붙여넣은 내용이 서버로 전송되나요?
전송되지 않습니다. 파싱은 브라우저에서 이루어집니다. 그렇더라도 운영 환경의 실제 자격증명이 담긴 .env 를 외부 사이트에 붙여넣는 것은 권장하지 않습니다. 문법을 확인하려는 목적이라면 값을 더미로 바꿔서 확인하세요.
값에 줄바꿈을 넣으려면 어떻게 하나요?
파서가 지원하는 경우 큰따옴표로 감싸고 실제 줄바꿈을 넣거나 \n 이스케이프를 씁니다. 다만 지원 여부가 라이브러리마다 달라, RSA 개인키처럼 여러 줄인 값은 실무에서 Base64로 한 번 인코딩해 한 줄로 저장하고 코드에서 디코딩하는 방식을 자주 씁니다. 플랫폼 UI에 직접 입력하는 경우에는 대개 여러 줄이 그대로 지원됩니다.
값에 # 이 들어가면 잘립니다.
인라인 주석으로 해석된 것입니다. 값 전체를 따옴표로 감싸면 해결됩니다. 비밀번호에 #, $, 공백, 따옴표 같은 문자가 있으면 작은따옴표로 감싸는 것이 가장 예측 가능합니다.
왜 .env 값이 적용되지 않나요?
확인 순서는 이렇습니다. 파일이 프로세스의 작업 디렉터리에 있는지(하위 디렉터리에서 실행하면 못 찾습니다), 로드 코드가 다른 import보다 먼저 실행되는지, 이미 셸에 같은 이름의 환경변수가 설정되어 있어 이기고 있는지, 그리고 파일 이름이 정확한지(.env.txt 로 저장된 경우가 흔합니다).
키에 하이픈을 쓸 수 있나요?
일부 파서는 읽어 들이지만 쓰지 마세요. 하이픈이 있는 이름은 셸에서 환경변수로 export할 수 없어 도구 간 이동이 불가능해집니다. 밑줄을 쓰는 것이 관례이자 실용적인 선택입니다.
빈 값과 정의되지 않은 값은 다른가요?
다릅니다. KEY= 는 빈 문자열이 설정된 상태이고, 아예 없으면 undefined 입니다. JavaScript에서 process.env.KEY ?? "default" 는 빈 문자열을 유지하지만 process.env.KEY || "default" 는 빈 문자열을 기본값으로 대체합니다. 이 차이가 의도치 않은 동작을 만들 수 있으니 어느 쪽이 필요한지 정해서 쓰세요.

💡 참고: 값이 이상하게 들어갔다고 느껴지면 이 도구로 파싱 결과를 먼저 확인하세요. 따옴표가 값에 포함되어 있거나 특수문자에서 잘려 있는 경우가 대부분입니다.

🔗관련 도구🧰 기타 도구