dotenv로 환경 변수 관리하기
Jan 12, 2021 · 4 min read



이번 포스트에서는 환경 변수를 파일에 저장할 수 있도록 해주는 dotenv 라이브러리에 대해서 알아보겟습니다.

설치

npm 패키지 매니저를 이용하여 dotenv 라이브러리를 Node.js 프로젝트에 설치합니다.

$ npm i dotenv

.env 파일 작성

dotenv 라이브러리는 디폴트로 현재 디렉토리에 위치한 .env 파일로 부터 환경 변수를 읽어냅니다. 따라서, .env 파일을 생성하고, 그 안에 필요한 환경 변수를 키=값의 포멧으로 나열하도록 하겠습니다.

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

이렇게 .env 파일에 저장해놓은 환경 변수들을 dotenv 라이브러리를 이용해서 process.env에 설정할 수 있는데요.

Node.js에서 process.env를 통해서 환경 변수 다루는 방법은 지난 포스트를 참고 바랍니다.

본인 프로젝트가 CommonJS 기반인지 ES 모듈 기반인지에 따라 라이브러리 사용법이 약간 상이하므로 나눠서 설명드리도록 하겠습니다.

CommonJS에서 환경 변수 불러오기 (require)

먼저 Node.js에서 전통적으로 제공해왔던 모듈 시스템인 CommonJS에서 dotenv 라이브러리를 어떻게 사용하는지 알아보겠습니다.

애플리케이션을 구동할 때 제일 먼저 실행되는 자바스크립트 파일(ex. index.js, main.js)의 최상위에 다음과 같이 dotenv 라이브러를 임포트한 후 config() 함수를 호출해주기만 하면 됩니다.

// index.js

require("dotenv").config()

console.log("DB_HOST:", process.env.DB_HOST)
console.log("DB_USER:", process.env.DB_USER)
console.log("DB_PASS:", process.env.DB_PASS)

예를 들어, 위 코드를 실행하면 process.env로 부터 읽어진 확경 변수가 출력되는 것을 볼 수 있습니다.

DB_HOST: localhost
DB_USER: root
DB_PASS: s1mpl3

하지만, 같은 파일 내에서 dotenv 라이브러리의 config() 함수를 호출하기 전에 process.env를 읽으면 안 되니 주의하셔야 합니다.

// index.js

console.log("DB_HOST:", process.env.DB_HOST)
console.log("DB_USER:", process.env.DB_USER)
console.log("DB_PASS:", process.env.DB_PASS)

require("dotenv").config()
DB_HOST: undefined
DB_USER: undefined
DB_PASS: undefined

만약에 .env가 아닌 다른 경로에 있는 파일에 환경 변수를 저장해놨다면 config() 함수를 호출 시 path 옵션을 넘기면 됩니다.

require("dotenv").config({ path: "/path/to/.env.local" })

ES 모듈에서 환경 변수 불러오기 (import)

require 대신에 import 키워드를 사용하는 ES 모듈에서는 dotenv 라이브러리를 어떻게 사용할까요?

ES 모듈을 사용할 때는 CommonJS를 사용할 때 보다 좀 더 주의가 필요한데요. 흔히 발생하는 문제를 재현해보겠습니다.

아래 코드를 보시면, dotenv 라이브러리를 제일 임포트하기 때문에 db.js 파일이 process.env에 접근할 때 환경 변수가 설정이 되어 있을 것 같습니다.

// db.js

export const db_host = process.env.DB_HOST
export const db_user = process.env.DB_USER
export const db_pass = process.env.DB_PASS
// index.js

import dotenv from "dotenv"
import { db_host, db_user, db_pass } from "./db.js"

dotenv.config()

console.log("DB_HOST:", process.env.DB_HOST)
console.log("DB_USER:", process.env.DB_USER)
console.log("DB_PASS:", process.env.DB_PASS)

console.log({ db_host, db_user, db_pass })

하지만 실제 실행을 해보면 db.js 파일이 process.env에 접근했을 시점에는 환경 변수가 설정이 되어 있지 않았던 것을 알 수 있습니다.

DB_HOST: localhost
DB_USER: root
DB_PASS: s1mpl3
{ db_host: undefined, db_user: undefined, db_pass: undefined }

이러한 현상이 발생하는 이유는 dotenv.config() 함수가 db.js 파일이 임포트 된 이후에 호출되었기 때문입니다.

이 문제는 dotenv 라이브러리를 임포트하는 코드를 별도의 파일로 빼고, 그 안에서 dotenv.config() 함수를 호출하면 피할 수 있습니다.

// env.js

import dotenv from "dotenv"

dotenv.config()
// index.js

import "./env.js"
import { db_host, db_user, db_pass } from "./db.js"

console.log("DB_HOST:", process.env.DB_HOST)
console.log("DB_USER:", process.env.DB_USER)
console.log("DB_PASS:", process.env.DB_PASS)

console.log({ db_host, db_user, db_pass })
DB_HOST: localhost
DB_USER: root
DB_PASS: s1mpl3
{ db_host: 'localhost', db_user: 'root', db_pass: 's1mpl3' }

node 커맨드 -r 옵션 사용

본인 프로젝트가 CommonJS 기반인지 ES 모듈 기반인지 신경쓰기 싫으시다면 node 커맨드를 이용하는 방법도 있습니다. 애플리케이션을 구동할 때, node 커맨드의 -r 또는 --require 옵션으로 dotenv/config를 넘기는 것입니다.

$ node -r dotenv/config index.js

이 방법을 사용하면 dotenv 라이브러리를 코드에 직접 임포트하지 않아도 .env 파일에 저장된 환경 변수가 process.env에 설정됩니다.

// index.js

console.log("DB_HOST:", process.env.DB_HOST)
console.log("DB_USER:", process.env.DB_USER)
console.log("DB_PASS:", process.env.DB_PASS)
DB_HOST: localhost
DB_USER: root
DB_PASS: s1mpl3

만약에 .env가 아닌 다른 경로에 있는 파일에 환경 변수를 저장해놨다면 DOTENV_CONFIG_PATH 환경 변수를 사용하면 됩니다.

$ DOTENV_CONFIG_PATH=/path/to/.env.local node -r dotenv/config index.js

마치면서

이상으로 dotenv 라이브러리를 이용해서 파일에 환경 변수를 저장해놓고 불러오는 방법에 대해서 대략적으로 살펴보았습니다. dotenv 라이브러리에 좀 더 자세한 내용은 Github를 참고하시기 바랍니다.






Engineering Blog  by Dale Seo