일반적으로 서비스를 개발할 때,
이렇게 실행환경이 달라지면, 실행환경에 따라 달라지는 환경 변수들이 존재한다.
(예시)
로컬 환경: localhost
스테이지 환경: stage-ver.com
프로덕션 환경: product-ver.com
따라서 실행 환경에 따라 서버에 설정되는 환경변수 파일을 분리 및 관리하는 것이 좋다
두가지 방법이 있다: dotenv 라이브러리 사용, nestjs/config 모듈 사용
위에서 언급했듯이, 환경변수 파일을 실행환경에 따라 다르게 구성해야하므로
.development.env
DATABASE_HOST=local
.stage.env
DATABASE_HOST=stage-ver.com
.production.env
DATABASE_HOST=product-ver.com
※ NODE_ENV에 대한 내용과 생성 방법은 아래에 자세히..
main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv'
import * as path from 'path'
dotenv.config({
path: path.resolve(
process.env.NODE_ENV === 'production') ? '.production.env'
: (process.env.NODE_ENV === 'stage') ? '.stage.env' : '.development.env'
)
});
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
dotenv의 환경을 설정한다. .env파일의 경로를 NODE_ENV의 값에 따라 다르게 지정한다.
아래처럼 예시로 환경변수 DATABASE_HOST의 값을 출력하는 코드를 작성한 후 확인해본다
app.controller.ts
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return process.env.DATABASE_HOST;
}
}
설치 : yarn add @nestjs/config
.dev.env
이름의 development 환경 변수 파일을 생성했다. (위치: src > configs > env)
※ 주의할 점: 앞으로 env파일에는 민감한 정보가 들어갈 것이기 때문에 .gitignore파일에 env를 추가하여 깃허브에 푸쉬되지 않도록 해야한다.
.gitignore
**/*.env
Node.js는 NODE_ENV라는 환경 변수를 활용하여 서버의 환경을 구분한다.
매번 터미널을 새로 열때마다 NODE_ENV를 새로 설정하는 것은 귀찮은 일이니, package.json파일을 수정하여 yarn start:dev
명령이 수행될 때 NODE_ENV가 dev(개발)로 설정되도록 했다.
package.json
"scripts": {
....
"start:dev": "cross-env NODE_ENV=dev nest start --watch", // cross-env를 명시
},
단순히 “NODE_ENV=dev nest start --watch”로만 설정할 경우, Mac OS와 Linux에서는 돌아가지만 Window OS에서는 인식이 안된다는 문제점이 있다.
cross-env모듈은 프로젝트 참여자 각각이 MacOS, Windows, Linux 등 다양한 OS 마다 환경변수를 설정하는 방법이 다르기 때문에 이것에 대한 대책을 마련한 모듈이다.
cross-env모듈을 사용하면 OS간의 호환성 문제를 해결할 수 있다.
yarn add cross-env
참고 : https://inpa.tistory.com/entry/NODE-📚-cross-env-모듈-사용법
이제 .env파일을 NODE_ENV에 따라 읽을 수 있다.
app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: `src/configs/env/.${process.env.NODE_ENV}.env`, 💚
isGlobal: true, 💛 // 전체적으로 사용하기 위해
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
💚 envFilePath에는 env파일이 위치한 경로를 적어준다
💛 전역 모듈로 동작하게 하여 어느 모듈에서나 사용할 수 있게 해준다.
Typescript 코드가 Node.js에서 작동하기 위해 Javascript코드로 컴파일되는 과정이 필요하다.
Typescript가 Javascript로 바뀌어서 dist라는 폴더로 들어가서 실행된다. (dist 폴더는 실제 배포 단계에서 사용된다.)
이때 .env파일은 자동으로 dist폴더로 복사되지 않는다. 따라서 .env파일을 out디렉토리(dist 디렉토리)에 복사할 수 있도록 nest-cli.json에서 옵션을 수정해야한다.
nest-cli.json
{
....
"compilerOptions": {
"assets": [
{
"include": "./configs/env/*.env",
"outDir": "./dist"
}
]
}
}
app.service.ts를 약간 수정해서 yarn start:dev
로 한번 확인해보자
app.service.ts
@Injectable()
export class AppService {
getHello(): string {
return `Hello World! ${process.env.NAME}`;
}
}
.dev.env
NAME = Seunghyeon
Nest는 dotenv를 내부적으로 쉽게 활용할 수 있는 @nest/config 패키지를 제공하기 때문에 @nest/config 활용을 추천한다.
참고 도서 : NestJS로 배우는 백엔드 프로그래밍