← Notes

Nest.js 환경 변수 관리 — Config Module

Nest.js 백엔드 개발· 8 / 8
  1. 1 — Nest.js 프로젝트 생성과 구조
  2. 2 — Nest.js Decorator 동작원리와 종류, Custom Decorator
  3. 3 — Nest.js 의존성 주입 개념과 적용 방법
  4. 4 — Nest.js HTTP exceptions 에러 처리 모음
  5. 5 — Nest.js CORS 설정
  6. 6 — Nest.js 유효성 검사 — Validation Pipe와 class-validator
  7. 7 — Nest.js API 문서화 — Swagger Module
  8. 8 — Nest.js 환경 변수 관리 — Config Module

이전까지 스터디로 프로젝트를 해오면서 환경변수 설정을 제대로 사용해본 적이 없었다.

프로젝트 규모도 작고 외부에 노출되면 안 되는 설정 자체가 많지 않다보니 크게 신경쓰지 않았다. 게다가 개발환경과 배포환경의 차이를 명확히 이해하지 못해 환경별로 설정을 다르게 하는 필요성을 느끼지 못했고, 왜 해주어야 하는지도 몰랐다.

현업과 스터디를 해오면서 민감한 정보인 데이터베이스 정보나 OpenAPI Key 등을 다루고 개발환경과 배포환경의 차이를 알게 되면서 환경변수 설정의 중요성을 느끼게 되었다.

현재 진행 중인 프로젝트에서는 NestJS의 ConfigModule이라는 공식 라이브러리를 활용해 환경변수를 사용하고 있다. 무엇인지 정리해보자.

ConfigModule

ConfigModule를 설정하는 이유

config 설정을 분리해서 관리하는 가장 큰 두 가지 이유는 보안과 환경설정이다.

프로그램 내에서 사용하는 외부 API Key, DB 접속 정보 등 외부 공개에 민감한 보안 정보를 숨기고, 환경에 따라 설정을 다르게 두어 개발/테스트/배포 환경을 구분할 수 있다.

Node.js에서는 환경변수를 읽어오기 위해 주로 dotenv 라이브러리를 사용하는데, Nest.js에서는 공식 라이브러리인 @nestjs/config를 이용해 좀더 유연하고 확장 가능한 방식으로 환경변수 설정을 관리할 수 있다.

.env 파일 외 다양한 파일에서 환경변수를 읽어올 수 있고, 타입스크립트 지원이나 동적으로 불러오는 등 다양한 기능을 제공한다고 한다.

ConfigModule 설정

먼저 라이브러리를 설치해야 한다. Nest.js 전용 환경변수 라이브러리를 설치해준다.

npm install @nestjs/config

환경변수 관리는 ConfigModule이 담당하는데 ConfigModuleapp.module.ts에 임포트한다.

import { Module } from '@nestjs/common';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { ConfigModule } from '@nestjs/config';

const nodeEnv = process.env.NODE_ENV || 'development';
const envFilePath = `.env.${nodeEnv}`;

@Module({
  imports: [
    ConfigModule.forRoot({
			isGlobal: true,
      envFilePath,
    }),
  ],
})
export class AppModule {}

먼저 process.env.NODE_ENV으로 개발환경과 배포환경에 따라 .env 파일을 로드해 ConfigModule에 지정해두었다.

Configodule을 임포트하면 기본적으로 루트 디렉토리에 있는 .env 파일을 읽어오게 설정되어 있다.

포함된 옵션은 아래와 같다.

  • isGlobal: true로 설정할 경우, 기능성 모듈에 Configodule를 별도로 임포트해주지 않아도 전역에서 환경변수를 읽어오는 ConfigService를 사용할수 있다.(default: false)
  • envFilePath: 다른 이름의 .env 파일을 정적으로 지정하고 싶을 경우 사용한다.

ConfigService 활용

테스트를 위해 몇가지 환경변수 예시를 .env.development 파일에 추가해주었다.

DB_HOST = '127.0.0.1'
DB_PORT = 3306
DB_USERNAME = 'username'
DB_PASSWORD = 'password'
DB_DATABASE = 'database'

지정한 환경변수 정보를 불러와 TypeORM 데이터베이스 설정 파일에 적용한다.

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from '@nestjs/typeorm';

@Injectable()
export class TypeOrmConfig implements TypeOrmOptionsFactory {
  constructor(private readonly configService: ConfigService) {}

  createTypeOrmOptions(): TypeOrmModuleOptions {
    return {
      type: 'mysql',
      host: this.configService.get<string>('DB_HOST'),
      port: this.configService.get<number>('DB_PORT'),
      username: this.configService.get<string>('DB_USERNAME'),
      password: this.configService.get<string>('DB_PASSWORD'),
      database: this.configService.get<string>('DB_DATABASE'),
      entities: ...
    };
  }
}

먼저 @nestjs/config에서 제공하는 ConfigService를 클래스에 주입한 후, get()함수를 이용해 설정해둔 환경변수를 불러와 적용할 수 있다.

현재는 .env 파일에 있는 환경변수를 각각 읽어오는 방식으로 사용하기 때문에 코드 다소 지저분하고 가독성을 해칠 우려가 있지만, .env 파일이 아닌 .json이나 .config 등 다른 파일로 환경변수를 관리한다면 좀더 가독성과 활용력이 높은 방식으로 환경변수를 사용할 수 있다.

참고 자료

  • [1] Documentation | NestJS
목차