Configuration

Configuration

응용 프로그램은 다른 환경에서 실행되는 데 사용되곤 합니다. 환경에 따라 다양한 구성 변수 세트를 사용해야 합니다. 예를 들어, 로컬 환경은 특정 데이터베이스 자격 증명에 의존할 가능성이 매우 높으며 로컬 DB 인스턴스에만 유효합니다. 이 문제를 해결하기 위해 키-값 쌍을 보유하는.env 파일을 활용했습니다. 이 방법은 매우 편리하므로 각 키는 특정 값을 나타냅니다.

그러나 프로세스 전역 객체를 사용하는 경우 테스트된 클래스가 직접 사용할 수 있으므로 테스트를 깨끗하게 유지하기가 어렵습니다. 또 다른 방법은 로드된 구성 변수로 ConfigService를 노출하는 추상화 계층 인 ConfigModule을 작성하는 것입니다.

Installation

특정 플랫폼은 환경 변수를process.env 전역에 자동으로 연결합니다. 그러나 로컬 환경에서는 수동으로 관리해야 합니다. 환경 파일을 구문 분석하기 위해 dotenv 패키지를 사용합니다.

$ npm i --save dotenv
$ npm i --save-dev @types/dotenv

Service

먼저 ConfigService 클래스를 만들어 봅시다.

@@filename()
import * as dotenv from 'dotenv';
import * as fs from 'fs';

export class ConfigService {
  private readonly envConfig: { [key: string]: string };

  constructor(filePath: string) {
    this.envConfig = dotenv.parse(fs.readFileSync(filePath))
  }

  get(key: string): string {
    return this.envConfig[key];
  }
}
@@switch
import * as dotenv from 'dotenv';
import * as fs from 'fs';

export class ConfigService {
  constructor(filePath) {
    this.envConfig = dotenv.parse(fs.readFileSync(filePath))
  }

  get(key) {
    return this.envConfig[key];
  }
}

이 클래스는.env 파일의 경로 인 filePath라는 단일 인수를 취합니다. get()메소드는 환경 파일 내에 정의된 각 속성을 보유하는 개인 envConfig 오브젝트에 액세스할 수 있도록 제공됩니다.

마지막 단계는 ConfigModule을 만드는 것입니다.

@@filename()
import { Module } from '@nestjs/common';
import { ConfigService } from './config.service';

@Module({
  providers: [
    {
      provide: ConfigService,
      useValue: new ConfigService(`${process.env.NODE_ENV}.env`),
    },
  ],
  exports: [ConfigService],
})
export class ConfigModule {}

ConfigModuleConfigService를 등록하고 이를 내 보냅니다. 또한 .env 파일의 경로를 전달했습니다. 이 경로는 실제 실행 환경에 따라 다릅니다. 이제 어디서나 ConfigService 를 주입하고 전달된 키를 기반으로 특정 값을 가져올 수 있습니다. 샘플 .env 파일은 다음과 같습니다.

DATABASE_USER = test
DATABASE_PASSWORD = test

Using the ConfigService

ConfigService에서 환경 변수에 액세스하려면 변수를 주입해야합니다. 따라서 먼저 모듈을 가져와야합니다.

@@filename(app.module)
@Module({
  imports: [ConfigModule],
  ...
})

그런 다음 주입 토큰을 사용하여 주입할 수 있습니다. 기본적으로 토큰은 클래스 이름과 같습니다 (예: ConfigService).

@@filename(app.service)
@Injectable()
export class AppService {
  private isAuthEnabled: boolean;
  constructor(config: ConfigService) {
    // Please take note that this check is case sensitive!
    this.isAuthEnabled = config.get('IS_AUTH_ENABLED') === 'true';
  }
}

info 힌트 모든 모듈에서 ConfigModule을 가져 오는 대신 ConfigModule을 전역 모듈로 선언할 수도 있습니다.

Advanced configuration

방금 기본 ConfigService를 구현했습니다. 그러나 이 접근 방식에는 몇 가지 단점이 있습니다.

  • 환경 변수에 대한 이름 및 유형 누락 (IntelliSense 없음)

  • 제공된.env 파일의 확인 부족

  • env 파일은 부울을 문자열 ('true')로 제공하므로 매번 부울로 캐스트해야합니다.

Validation

제공된 환경 변수의 유효성 검증부터 시작하겠습니다. 필요한 환경 변수가 제공되지 않았거나 사전 정의된 요구 사항을 충족하지 않으면 오류가 발생할 수 있습니다. 이를 위해 npm 패키지 Joi를 사용합니다. Joi를 사용하면 객체 스키마를 정의하고 이에 대해 JavaScript 객체의 유효성을 검사합니다.

Joi 설치 및 유형 (TypeScript 사용자의 경우) :

$ npm install --save @hapi/joi
$ npm install --save-dev @types/hapi__joi

패키지가 설치되면 ConfigService로 이동할 수 있습니다.

@@filename(config.service)
import * as dotenv from 'dotenv';
import * as Joi from '@hapi/joi';
import * as fs from 'fs';

export interface EnvConfig {
}

export class ConfigService {
  private readonly envConfig: EnvConfig;

  constructor(filePath: string) {
    const config = dotenv.parse(fs.readFileSync(filePath));
    this.envConfig = this.validateInput(config);
  }

  /**
   * Ensures all needed variables are set, and returns the validated JavaScript object
   * including the applied default values.
   */
  private validateInput(envConfig: EnvConfig): EnvConfig {
    const envVarsSchema: Joi.ObjectSchema = Joi.object({
      NODE_ENV: Joi.string()
        .valid(['development', 'production', 'test', 'provision'])
        .default('development'),
      PORT: Joi.number().default(3000),
      API_AUTH_ENABLED: Joi.boolean().required(),
    });

    const { error, value: validatedEnvConfig } = Joi.validate(
      envConfig,
      envVarsSchema,
    );
    if (error) {
      throw new Error(`Config validation error: ${error.message}`);
    }
    return validatedEnvConfig;
  }
}

NODE_ENVPORT에 기본값을 설정했으므로 환경 파일에 이러한 변수를 제공하지 않으면 유효성 검사가 실패하지 않습니다. 그럼에도 불구하고 명시적으로 API_AUTH_ENABLED를 제공해야 합니다. 스키마의 일부가 아닌 .env 파일에 변수가 있는 경우 유효성 검사에서도 오류가 발생합니다. 또한 Joi는 env 문자열을 올바른 유형으로 변환하려고 시도합니다.

Class properties

각 구성 속성마다 getter 함수를 추가해야합니다.

@@filename(config.service)
get isApiAuthEnabled(): boolean {
  return Boolean(this.envConfig.API_AUTH_ENABLED);
}

Usage example

이제 클래스 속성에 직접 액세스 할 수 있습니다.

@@filename(app.service)
@Injectable()
export class AppService {
  constructor(config: ConfigService) {
    if (config.isApiAuthEnabled) {
      // Authorization is enabled
    }
  }
}

Last updated