Envrioment Variables
, 환경변수는 프로세스가 컴퓨터에서 동작하는 방식에 영향을 미치는 동적인 값들의 모임이라고 정의되어있습니다. 즉 운영체제 상에서 동작하는 응용소프트웨어가 참조하기 위한 설정들이 기록되는 곳입니다.
웹 애플리케이션에도 어플리케이션이 동작하기 위해 필요한 중요한 정보들이 존재합니다. DB 연결을 위한 계정명과 비밀번호, OAuth 로그인을 위해 인증서버에 요청하기 위한 키 등 중요한 정보들을 공개된 저장소에 올리는 외부 노출행위를 방지해야합니다. 그래서 환경변수로 저장해놓고 사용해야합니다.
NodeJS
프로세스에 대한 정보와 제어를 제공하는 process
라는 객체를 지원하고있습니다. process.env
라는 명령어를 통해 환경변수에 접근합니다. 이제 알아야할 것은 TypeScript
+ Express
프로젝트에 환경변수를 어떻게 적용해야하나 입니다. 라이브러리부터 알아봅시다.
dotenv
"@types/dotenv"
cross-env
실제 배포될 앱을 위한 production
, 개발 환경에서 활용할 development
등등 NODE_ENV
에다가 변수를 담아두고 작업하는 것으로 알고있습니다. 하지만 TypeScript
프로젝트에서 Node_ENV
가 없으므로 definition type
을 생성해 줘야합니다.
declare namespace NodeJS {
interface ProcessEnv {
readonly NODE_ENV?: 'development' | 'production' | 'test';
}
}
이제 각 타입에 맞는 환경변수 파일들을 생성해줍니다.
IM=develop
PORT=
HOST=
GITHUB_ID=
....
IM=prod
PORT=
HOST=
GITHUB_ID=
....
IM=test
PORT=
HOST=
GITHUB_ID=
....
동적인 환경변수는 보통 동일 OS
에서만 사용이 가능합니다.
"prod": "NODE_ENV=production nodemon --exec ./dist/src/server.js",
"dev": "NODE_ENV=development nodemon --exec \"ts-node\" ./src/server.ts
예를 들어, MacOS에서 환경변수를 이렇게 가져다 쓰면, Windows나 Linux에서도 동일한 설정으로 환경변수에 접근하기위해 cross-env
를 사용해줍니다.
"prod": "cross-env NODE_ENV=production nodemon --exec ./dist/src/server.js",
"dev": "cross-env NODE_ENV=development nodemon --exec \"ts-node\" ./src/server.ts"
이제 src/Config/
디렉토리안에 .env.production
, .env.development
, .env.test
파일을 가져와야합니다.
제가 작성한 코드는 다음과 같습니다.
import { config as configENV } from 'dotenv';
import { resolve } from 'path';
const root: string = `${process.cwd()}/src/.env/`;
console.log(process.env.NODE_ENV);
switch (process.env.NODE_ENV) {
case 'development':
configENV({
path: resolve(root + '.env.development'),
});
break;
case 'production':
configENV({
path: resolve(root + '.env.production'),
});
break;
case 'test':
configENV({
path: resolve(root + '.env'),
});
default:
throw new Error(`NODE_ENV: ${process.env.NODE_ENV}를 불러올 수 없습니다.`);
}
interface ThirdENV {
[key: string]: number | string | undefined;
}
export const MySqlENV: ThirdENV = {
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PWD,
port: Number(process.env.MYSQL_PROT),
database: process.env.MYSQL_DB,
};
Switch Case
문법으로 분기를 나눠줍니다.
저는 .env
를 다른 루트에 저장하고있기 때문에, dotenv
의 config 속성에 있는 path를 활용했습니다.
process.cwd()
는 현재위치가 아닌 프로젝트의 루트 디렉토리를 가져옵니다. 덕분에 __dirname
보다 환경변수 위치를 가져오는데 좀더 수월했습니다.
interface ThirdENV {
[key: string]: number | string | undefined;
}
export const MySqlENV: ThirdENV = {
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PWD,
port: Number(process.env.MYSQL_PROT),
database: process.env.MYSQL_DB,
};
이부분은 다른 플렛폼이나, 데이터베이스에 접근할 정보를 미리 생성해뒀습니다.