동적 모듈은 모듈이 생성 될대 동적으로 어떠한 변수들이 정해집니다.
즉 호스트 모듈을 가져다 쓰는 소비 모듈에서 호스트 모듈을 생성할 때 동적으로 값을 설정하는 방식 입니다
정적 모듈에 비해 동적 모듈ㅇ르 사용하면 코드가 간결해집니다.
동적 모듈의 대표적인 예로 보통 config 라고 부르는 모듈이 있습니다.
Config 모듈은 실행 환경에 따라 서버에 설정되는 환경 변수를 관리하는 모듈입니다.
ConfigModule을 동적으로 생성하는 예를 보기 전에 잠시 NodeJS 서버에서 일반적으로 사용하는 환경 변수 관리 방법을 살펴 보겠다.
.env
를 이용한 Config 설정
서비스를 개발할 때 local 혹은 development라 부르는 개발자 PC환경에서 개발과 테스트를 하고 개발한 코드를 stage 서버라고 부릅니다.
테스트 환경에 배포하여 통합 테스트를 진행합니다.
이후 테스트 서버 환경에 문제가 없다면 다시 production 서버로 배포하는 과정을 거칩니다ㅣ.
이렇게 실행 환경이 달라지게 되는데 실행 환경에 따라 달라지는 변수들이 있습니다.
연결할 데이터 베이스의 호스트 이름이 DATABASE_HOST
라는 환경 변수가 있다고 할 때 이 환경 변수의 값은 각각의 환경에 따라 다른 이름을 가지게 됩니다.
환경 마다 다른 host 이름을 가지는 데이터 베이스에 연결하기 위해 코드를 따로 작성해야 하는 것은 매우 비효율 적입니다.
NodeJS에는 dotenv
라는 유명한 라이브러리가 존재합니다.
각 환경 변수를 .env
확장자를 가진 파일에 저장해두고, 서버가 구동될때, 이 파일을 읽어 해당 값을 환경 변수로 설정해주는 역할을 합니다.
npm i --save dotenv
npm i --save-dev @types/dotenv
dotenv
는 기본으로 루트 디렉터리에 존재하는 .env
확장자를 가진 파일을 읽습니다.
위에서 예로 들었던 DATABASE_HOST
라는 환경 변수를 각 파일에 저장합니다.
.development.env
DATABASE_HOST=local
.stage.env
DATABASE_HOST=stage-reader.dextto.com
.production.env
DATABASE_HOST=prod-reader .dextto.com
매번 터미널을 새로 열때마다, NODE_ENV
를 새로 설정하는 것은 귀찮기 때문에, package.json
에 아래와 같이 셋팅하게 된다면, 간편하게 셋팅이 가능하다.
"scripts":{
"prebuild": "rimraf dist",
...
"start:dev" : "npm run prebuild && NODE_ENV=development nest start --watch"
}
Nest에서 제공하는 Config 패키지
앞 절에서는 dotenv 패키지를 직접 사용하는 방법을 살펴 봤습니다.
그런데 Nest는 dotenv를 내부적으로 활용하는 @nestjs/config
패키지를 제공합니다.
이를 이용해서 ConfigModule을 동적으로 생성할 수 있습니다.
npm i --save @nestjs/config
이 패키지에는 ConfigModule 이름을 가진 모듈이 이미 존재합니다.
이 모듈을 동적 모듈로 가져옵니다.
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [ConfigModule.forRoot()],
})
export class AppModule { }
정적 모듈을 가져올 때와는 달리 ConfigModule.forRoot()
메서들르 호출하는 것을 볼 수 있습니다.
forRoot
메서드는 DynamicModule을 리턴하는 정적 메서드 입니다.
동적 모듈을 작성할 때 forRoot
라는 이름 대신 어떤 다른 이름을 써도 상관 없지만, 관례상 forRoot
나 register
를 붙입니다.
비동기 함수일 때는 forRootAsync
, registerAsync
로 합니다.
static forRoot(options?: ConfigModuleOptions) : DynamicModule
인수로는 ConfigModuleOptions
를 받습니다.
즉, ConfigModule
은 소비 모듈이 원하는 옵션값을 전달하여 원하는 대로 동적으로 ConfigModule
을 생성합니다.
ConfigModule
을 위와 같이 가져왔다면, 프로젝트의 루트 디렉터리에 있는 .env
파일을 찾아 환경 변수로 등록합니다.
우리는 3개의 .env
파일을 가지고 있으므로 envFilePath
옵션을 주도록 해야합니다.
import { ConfigModule } from '@nestjs/config'
@Module({
imports: [ConfigModule.forRoot({
envFilePath: (process.env.NODE_ENV === 'production' ) ? '.production.env'
: (process.env.NODE_ENV === 'stage' ) ? '.stage.env' : '.development.env'
})],
controllers: [AppController],
providers: [AppService, ConfigService],
})
export class AppModule{ }
User Service에 환경 변수 구성하기
npm i @nestjs/config
npm i joi
환경 변수의 유효성 검사를 위한 joi 라이브러리도 설치 하겠습니다.
.development.env
EMAIL_SERVICE=Gmail
EMAIL_AUTH_USER=YOUR_GMAIL
EMAIL_AUTH_PASSWORD=GMAIL_PASSWORD
EMAIL_BASE_URL=http://localhost:3000