동적 모듈
- 모듈이 생성될때 동적으로 어떠한 변수들이 정해지는 것.
- 모듈 인스턴스마다 다르게 결정되어야 하는 것들을 소비 모듈에서 지정할 수 있기 때문에 코드가 간결해지는 장점.
- 동적 모듈의 대표적인 예로 Config 모듈이 있음.
Config
- 실행 환경에 따라 서버에 설정되는 환경 변수(environmental variable)를 관리하는 모듈.
- 일반적으로 서비스를 개발할때 실행 환경이 3가지로 나뉘는데 다음과 같다.
1. Development Server : 개발자 PC 환경에서 개발및 테스트를 진행하게 되는 곳.
2. Stage Server : 개발한 코드를 테스트 환경에 배포하여 통합 테스트를 진행하는 곳.
3. Production Server : 실제 서비스 운영을 위한 환경
- 이렇게 실행 환경이 달라지게 되는데, 실행 환경에 따라 달라지는 변수들이 있다.
- 환경마다 다른 호스트 이름을 가지는 데이터베이스에 연결하기 위해 코드를 따로 작성하는 것은 매우 비효율적이다.
- 그렇기 때문에 우선 각 환경 변수를 .env 확장자를 가진 파일에 저장해두고 서버가 구동될 때 이 파일을 읽어 해당 값을 환경 변수로 설정해준다.
환경 변수 파일은 시크릿 키와 같이 민감한 정보가 저장되는 경우가 많다.
따라서 github에 배포되지 않도록 해야한다. 그러므로 환경 변수 파일을 .gitignore파일에 추가해야 한다.
- Node.js는 NODE_ENV라는 환경 변수를 활용하여 서버의 환경을 구분힌다.
- 다음 코드는 package.json 파일을 수정하여 yarn run start:dev 명령어가 수행될때 NODE_ENV가 development로 설정되도록 한다.
"scripts": {
"prebuild": "rimraf dist",
...
"start:dev": "yarn run prebuild && NODE_ENV=development nest start --watch",
...
}
- 또한 깨끗한 상태에서 다시 컴파일하도록 prebuild 명령을 먼저 수행한다.
- Node에서는 dotenv패키지를 직접 사용할 수 있지만, Nest는 dotenv를 내부적으로 활용하는 @nestjs/config 패키지를 제공한다.
- 이 패키지에는 ConfigModule 이름을 가진 모듈이 이미 존재한다.
...
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [ConfigModule.forRoot()],
...
})
export class AppModule { }
- 정적 모듈을 가져올때와는 달리 .forRoot() 메서드를 호출하는 것을 볼 수 있다.
forRoot()
- 동적 모듈을 리턴하는 정적 메서드이다.
- 인수로는 ConfigModuleOptions를 받는다.
- 즉, 소비 모듈이 원하는 옵션값을 전달하여 원하는대로 동적으로 ConfigModule을 생성한다.
ConfigModuleOptions에는 envFilePath 외에도 여러 가지 옵션이 있다.
import { ConfigFactory } from './config-factory.interface';
export interface ConfigModuleOptions {
cache?: boolean;
isGlobal?: boolean;
ignoreEnvFile?: boolean;
ignoreEnvVars?: boolean;
envFilePath?: string | string[];
encoding?: string;
validate?: (config: Record<string, any>) => Record<string, any>;
validationSchema?: any;
validationOptions?: Record<string, any>;
load?: Array<ConfigFactory>;
expandVariables?: boolean;
}
1) envFilePath
- 기본적으로 패키지는 응용 프로그램의 루트 디렉토리에서 .env 파일을 찾는다.
- .env파일의 다른 경로를 지정할때 envFilePath 옵션을 지정해 주면 된다.
import { Module } from '@nestjs/common';
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',
}),
...
],
2) isGlobal
- true로 지정해 준다면 다른 곳에서도 환경 변수를 불러와 사용할 수 있게 된다.
커스텀 Config 파일 작성
- 모든 환경 변수가 .env파일에 선언되어 있지만, 가져다 쓸 때는 DatabaseConfig, EmailConfig와 같이 의미 있는 단위로 묶어서 처리하고 싶을 때가 있다.
- 우선 이메일 관련 환경 변수를 관리하는 emailConfig.ts를 작성해보자.
- 이 코드에는 앞서 이메일을 발송하기 위해 사용했던 계정 정보와 패스워드를 작성한다.
// /src/config/emailConfig.ts
import { registerAs } from '@nestjs/config';
export default registerAs('email', () => ({
service: process.env.EMAIL_SERVICE,
auth: {
user: process.env.AUTHEMAIL,
pass: process.env.AUTHEMAILPASSWORD,
},
baseUrl: process.env.EMAIL_BASE_URL,
}));
- emailConfig.ts의 코드를 쉽게 설명하면 'email'이라는 토큰으로 ConfigFactory를 등록할 수 있는 함수라고 이해하면 된다.
동적 ConfigModule 등록
- 일반적으로 실행환경에 따른 .env파일은 루트 경로가 아니라 src/config/env 디렉토리에 모아서 관리한다.
- Nest의 기본 빌드 옵션은 .ts 파일 외에 asset은 제외하도록 되어 있다.
- 따라서 .env파일을 Out 디렉터리에 복사할 수 있도록 nest-cli.json에서 옵션을 바꿔줘야 한다.
Out Directory : 컴파일한 파일들을 저장하는 폴더.
{
...
"compilerOptions": {
"assets": [
{
"include": "./config/env/*.env",
"outDir": "./dist"
}
],
...
}
- 이제 AppModule.ts에 ConfigModule을 동적 모듈로 등록해보자.
...
import { validationSchema } from './config/validationSchema';
...
import emailConfig from './config/emailConfig';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: [`${__dirname}/config/env/.${process.env.NODE_ENV}.env`],
load: [emailConfig], // load 속성을 통해 앞에서 구성해둔 ConfigFactory를 지정함.
isGlobal: true,
validationSchema, // 환경변수 값에 대해 유효성 검사를 수행하도록 joi를 이용하여 유효성 검사 객체를 작성함.
}),
...
],
...
- 환경 변수의 값에 대해 유효성 검사를 수행하도록 joi를 이용하여 유효성 검사 객체를 작성한다.
import * as Joi from 'joi';
export const validationSchema = Joi.object({
EMAIL_SERVICE: Joi.string().required(),
EMAIL_BASE_URL: Joi.string().required().uri(),
AUTHEMAIL: Joi.string().required(),
AUTHEMAILPASSWORD: Joi.string().required(),
});
- 이제 emailConfig를 우리가 사용하려고 하는 곳에 주입받아 사용할 수 있다.
'Back-End > Nest.js' 카테고리의 다른 글
내장 로거 (0) | 2023.02.13 |
---|---|
파이프와 유효성 검사 (0) | 2023.02.01 |
멋사 2주차 JS decorator, MVC 패턴, Nest.js 찍먹 (0) | 2023.01.11 |
멋사 스터디 2주차 HTTP, RESTFUL,웹 프레임워크 (0) | 2023.01.10 |
TypeScript (0) | 2023.01.02 |