[NEST] 환경변수 관리법(.env) feat. @nestjs/config

김지원·2022년 4월 30일
5

nest

목록 보기
1/4
post-thumbnail

1. 개요 🤸‍♂️


서버 쪽 코드를 관리할 때 항상 사용하는 것이 하나 있습니다.
그것은 환경설정할 때 필요한 환경 변수들이다. Node 기준으로 .env 파일에서 관리를 하게 되는데
이것도 환경별로 나누어 사용할 경우가 있습니다.

이번에는 nest에서 사용하는 .env파일 사용법에 대해 정리해보려고 합니다.

2. 🤔 왜 @nestjs/config로?


기본적으로 express를 이용해 환경변수를 사용할 때는 dotenv 모듈을 이용해 관리했었습니다.

ex)

import * as dotenv from 'dotenv';

const PORT = process.env('PORT');

하지만 nestjs 공식문서에서는 @nestjs/config 모듈을 사용하는 것을 추천합니다.

사실 @nestjs/config 내부적으로는 dotenv를 사용하고 있어서 그대로 해도 되긴하지만 nestjs에 맞춰 나온 모듈이기 때문에 사용하는 것이 좋습니다.

3. 👨‍💻 설정 방법


필자의 환경은 dev, local로 나누었습니다.

그럼 그에 맞춰 .env파일도 다르게 구성해야된다.
product같은 경우는 클라우드 단에서 설정하면 되기 때문에 .env 파일을 따로 구성해주지않았습니다.

파일은 그래서 .dev.env, .local.env로 구성하였습니다.

app.module

import { ConfigModule } from '@nestjs/config';
...


@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true, // 전체적으로 사용하기 위해
      envFilePath: `.${process.env.NODE_ENV}.env`,
    })
  ]
  ...
})

이런 식으로 구성한 후 NODE_ENV를 사용해주기 위해 cross-env모듈을 하나 더 설치해줍니다.

package.json

"script": {
    "start:local": "cross-env NODE_ENV=local nest start --watch",
  	"start:devops": "cross-env NODE_ENV=dev nest start --watch",

}

이렇게 NODE_ENV를 적어주면 설정은 끝입니다..!

4. 👨‍💻 사용 방법


사실 사용방법은 여러가지가 있습니다.

원래 사용방법처럼 process.env.name 이런 식으로 사용할 수 있습니다.

하지만 isGlobal을 사용하지 않을 경우가 있겠죠

그런 경우에는 사용하는 주체에서 ConfigService를 import 해야합니다.

User.Service.ts

import { ConfigService } from '@nestjs/config';

@Injectable()
export class UserService {
 constructor (private readonly config: ConfigService) {}
  
 private domain = this.config.get<string>('GATEWAY_DOMAIN', 'localhost');
 ...
}

첫번째 인자에 환경변수 키값을 넣어준다. 그리고 두 번째 인자에 기본값을 넣어줄수도 있습니다. (undefined일 때)
필자는 nest의 방식인 configservice를 가져오는 방식으로 사용하고 있습니다!

5. 유효성 검사하기


이제 마지막 챕터라고 볼 수 있습니다.

환경 변수가 잘못 들어가거나 본인이 원하지않는 값으로 들어가는 경우도 있습니다.

필자는 다른 유효성 검사도 class-validatorclass-transformer를 사용하고 있었기 때문에 커스텀하여 사용하였습니다.

이 내용은 공식 홈페이지에도 나와있으니 보고 따라해도 좋습니다.

env.validation.ts

import { plainToClass } from 'class-transformer';
import { IsEnum, IsNumber, validateSync } from 'class-validator';

enum Environment {
  Local = "local",
  Dev = "dev",
}

class EnvironmentVariables {
  @IsEnum(Environment)
  NODE_ENV: Environment;

  @IsNumber()
  PORT: number;
}

export function validate(config: Record<string, unknown>) {
  const validatedConfig = plainToClass(
    EnvironmentVariables,
    config,
    { enableImplicitConversion: true },
  );
  const errors = validateSync(validatedConfig, { skipMissingProperties: false });

  if (errors.length > 0) {
    throw new Error(errors.toString());
  }
  return validatedConfig;
}

app.module.ts

import { ConfigModule } from '@nestjs/config';
import { validate } from 'src/util/validate/env.validation';
...


@Module({
  imports: [
    ConfigModule.forRoot({
      envFilePath: `.${process.env.NODE_ENV}.env`,
      validate
    })
  ]
  ...
})

이렇게 환경 변수가 늘어날 때마다 유효성 검사를 해주어 undefined값을 못찾아 고생하는 일 없게 도와주면 좋을 것 같습니다ㅎㅎ

이렇게 nest에서 환경변수를 관리하는 법을 정리해보았습니다.
더 좋은 방법이 있다면 알려주시면 감사하겠습니다!

profile
backend-developer

0개의 댓글