icon

환경 변수 관리와 비밀 정보 보호


 환경 변수 관리와 비밀 정보 보호는 안전하고 유연한 NestJS 애플리케이션 개발의 핵심 요소입니다.

 적절한 환경 변수 사용은 코드의 재사용성을 높이고 다양한 배포 환경에 대한 유연성을 제공하며 중요한 정보를 안전하게 관리할 수 있게 해줍니다.

환경 변수 관리 방법

 NestJS에서는 주로 두 가지 방법으로 환경 변수를 관리합니다.

  1. dotenv
npm install dotenv
import * as dotenv from 'dotenv';
dotenv.config();
 
console.log(process.env.DATABASE_URL);
  1. @nestjs/config
npm install @nestjs/config
import { ConfigModule } from '@nestjs/config';
 
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
})
export class AppModule {}

 @nestjs/config는 dotenv의 기능을 포함하면서 추가적인 기능(환경별 설정, 스키마 검증 등)을 제공하므로 NestJS 프로젝트에서는 @nestjs/config를 사용하는 것이 권장됩니다.

환경별 설정 관리

 다양한 환경(개발, 테스트, 생산)에 대한 설정을 관리하는 방법

  1. 환경별 .env 파일 생성
.env.development
.env.test
.env.production
  1. ConfigModule 설정
import { ConfigModule } from '@nestjs/config';
 
ConfigModule.forRoot({
  envFilePath: `.env.${process.env.NODE_ENV}`,
})
  1. 환경별 설정 파일 사용
import devConfig from './config/dev.config';
import prodConfig from './config/prod.config';
 
ConfigModule.forRoot({
  load: [process.env.NODE_ENV === 'production' ? prodConfig : devConfig],
})

비밀 정보 관리

  1. 환경 변수 사용
DATABASE_PASSWORD=mySecretPassword
API_KEY=myApiKey
  1. 비밀 정보 참조
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
 
@Injectable()
export class AppService {
  constructor(private configService: ConfigService) {}
 
  getDatabasePassword() {
    return this.configService.get<string>('DATABASE_PASSWORD');
  }
}

클라우드 서비스 시크릿 관리 통합

 AWS Secrets Manager 사용 예

  1. 의존성 설치
npm install @aws-sdk/client-secrets-manager
  1. 시크릿 관리자 서비스 구현
import { Injectable } from '@nestjs/common';
import { SecretsManager } from '@aws-sdk/client-secrets-manager';
 
@Injectable()
export class SecretsService {
  private readonly secretsManager: SecretsManager;
 
  constructor() {
    this.secretsManager = new SecretsManager({
      region: 'us-east-1',
    });
  }
 
  async getSecret(secretName: string): Promise<string> {
    const response = await this.secretsManager.getSecretValue({ SecretId: secretName });
    return response.SecretString;
  }
}

설정 값 유효성 검사

 Joi를 사용한 스키마 검증

import * as Joi from 'joi';
 
ConfigModule.forRoot({
  validationSchema: Joi.object({
    NODE_ENV: Joi.string()
      .valid('development', 'production', 'test')
      .default('development'),
    PORT: Joi.number().default(3000),
    DATABASE_URL: Joi.string().required(),
  }),
})

환경 변수와 설정 정보의 버전 관리

  1. .env.example 파일 사용
DATABASE_URL=postgres://username:password@host:5432/database
API_KEY=your_api_key_here
  1. .gitignore에 실제 .env 파일 추가
.env
.env.*
  1. CI/CD 파이프라인 통합
# .gitlab-ci.yml 예시
deploy:
  script:
    - echo "DATABASE_URL=$DATABASE_URL" >> .env
    - echo "API_KEY=$API_KEY" >> .env
    - npm run deploy

컨테이너화된 앱에서의 환경 변수 관리

 Docker를 사용할 때의 환경 변수 설정

  1. Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
  1. docker-compose.yml
version: '3'
services:
  app:
    build: .
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    env_file:
      - .env.production

Best Practices 및 주의사항

  1. 민감한 정보를 절대 버전 관리 시스템에 포함시키지 않기
  2. 운영 환경의 비밀 정보는 클라우드 제공업체의 시크릿 관리 서비스 사용 고려
  3. 환경 변수에 대한 기본값 설정으로 애플리케이션 실행 오류 방지
  4. 환경 변수 이름은 명확하고 일관성 있게 작성 (예 : UPPERCASE_WITH_UNDERSCORE)
  5. 설정 값에 대한 유효성 검사 및 타입 체크 반드시 수행
  6. 로깅 시 민감한 정보가 노출되지 않도록 주의
  7. 정기적으로 비밀 정보 로테이션 수행
  8. CI/CD 파이프라인에서 환경 변수 주입 시 보안에 주의
  9. 컨테이너화된 환경에서는 런타임 시 환경 변수 주입 고려
  10. 개발 팀 내 환경 변수 및 비밀 정보 관리 프로세스 수립 및 교육

 NestJS 애플리케이션에서 환경 변수 관리와 비밀 정보 보호는 애플리케이션의 안정성, 보안, 유지보수성을 크게 향상시킵니다.

 @nestjs/config 모듈을 활용하면 환경 변수를 효과적으로 관리하고, 다양한 환경에 대응할 수 있는 유연한 설정이 가능합니다.