TIL - 20260220

juni·2026년 2월 20일

TIL

목록 보기
273/318

0220 NestJS 기초 (3/N): 유효성 검증(Validation)과 설정 관리(Config)


✅ 1. 유효성 검증 (Validation)

  • 클라이언트로부터 받은 데이터(e.g., DTO)가 우리가 기대하는 형식과 규칙에 맞는지 검증하는 것은, 애플리케이션의 안정성과 데이터 무결성을 위해 필수적인 과정입니다. NestJS는 파이프(Pipe)라는 메커니즘을 통해 이를 효율적으로 처리합니다.

➕ 1-1. 파이프 (Pipe)

  • 개념: @Injectable() 데코레이터가 붙은 클래스로, 들어오는 데이터를 변환(transformation)하거나 유효성을 검사(validation)하는 역할을 합니다.
  • 동작 방식: 파이프는 컨트롤러의 라우트 핸들러가 실행되기 직전에 위치하여, 요청 데이터(@Body, @Param 등)를 가로채 처리합니다.
  • 주요 내장 파이프:
    • ValidationPipe: 유효성 검사를 수행.
    • ParseIntPipe: 문자열을 숫자로 변환.
    • ParseBoolPipe: 문자열을 불리언으로 변환.

➕ 1-2. class-validatorclass-transformer

  • NestJS는 유효성 검사를 위해 class-validatorclass-transformer라는 매우 강력한 라이브러리를 함께 사용합니다.
  1. class-validator:

    • 역할: DTO 클래스의 속성(property)에 데코레이터를 붙여, 유효성 검증 규칙을 선언적으로 정의할 수 있게 해줍니다.
    • 주요 데코레이터: @IsString(), @IsNumber(), @IsNotEmpty(), @MinLength(), @IsEmail() 등.
  2. class-transformer:

    • 역할: 일반 JavaScript 객체(Plain Object)를 우리가 정의한 DTO 클래스의 인스턴스로 변환해줍니다. 이 변환 과정이 있어야 class-validator가 동작할 수 있습니다.

➕ 1-3. ValidationPipe 적용하기

  1. 필요한 패키지 설치:

    npm install class-validator class-transformer
  2. DTO에 유효성 검증 데코레이터 추가:

    // create-movie.dto.ts
    import { IsString, IsNumber, IsNotEmpty } from 'class-validator';
    
    export class CreateMovieDto {
      @IsString()
      @IsNotEmpty()
      readonly title: string;
    
      @IsNumber()
      readonly year: number;
    }
  3. main.ts에 전역 파이프(Global Pipe)로 등록:

    • ValidationPipe를 전역으로 등록하면, 모든 컨트롤러의 모든 라우트 핸들러에 들어오는 데이터에 대해 자동으로 유효성 검사가 적용됩니다.
    // main.ts
    import { ValidationPipe } from '@nestjs/common';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      app.useGlobalPipes(
        new ValidationPipe({
          whitelist: true, // DTO에 정의되지 않은 속성은 자동으로 제거
          forbidNonWhitelisted: true, // DTO에 정의되지 않은 속성이 있으면 요청 자체를 거부
          transform: true, // 요청 데이터를 DTO의 타입으로 자동 변환 (e.g., string -> number)
        }),
      );
      await app.listen(3000);
    }
    bootstrap();
  • 결과: 이제 CreateMovieDto를 사용하는 컨트롤러에 잘못된 데이터(e.g., year에 문자열)가 들어오면, NestJS는 비즈니스 로직이 실행되기 전에 자동으로 400 Bad Request 에러를 응답합니다.

✅ 2. 설정 관리 (@nestjs/config)

  • 문제점: 데이터베이스 비밀번호, API 키, 포트 번호 등 환경에 따라 달라지는 설정 값들을 소스 코드에 직접 하드코딩하는 것은 매우 나쁜 관행입니다. (보안 취약, 유연성 저하)

  • @nestjs/config: NestJS의 공식 설정 관리 모듈로, .env 파일을 사용하여 환경 변수를 손쉽게 관리하고, 이를 애플리케이션 전반에서 안전하게 사용할 수 있도록 도와줍니다.

@nestjs/config 설정 및 사용법

  1. 필요한 패키지 설치:

    npm install @nestjs/config
  2. .env 파일 생성: 프로젝트 루트 디렉토리에 .env 파일을 만들고, 환경 변수를 KEY=VALUE 형식으로 저장합니다.

    # .env
    PORT=4000
    DB_HOST=localhost
    DB_PASSWORD=mysecretpassword
    • 중요: .env 파일은 민감한 정보를 포함하므로, .gitignore 파일에 반드시 추가하여 Git에 커밋되지 않도록 해야 합니다.
  3. 루트 모듈(app.module.ts)에 ConfigModule 등록:

    • ConfigModule.forRoot()를 사용하여 모듈을 등록합니다. isGlobal: true 옵션을 주면, 다른 모듈에서 별도로 ConfigModuleimport할 필요 없이 어디서든 ConfigService를 주입받아 사용할 수 있습니다.
    // app.module.ts
    import { ConfigModule } from '@nestjs/config';
    
    @Module({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true, // 전역 모듈로 설정
          envFilePath: '.env', // 사용할 .env 파일 경로
        }),
        // ...
      ],
    })
    export class AppModule {}
  4. ConfigService 주입 및 사용:

    • 설정 값이 필요한 클래스(서비스, 컨트롤러 등)의 생성자에서 ConfigService를 주입받습니다.
    • configService.get('KEY') 메서드를 사용하여 .env 파일에 정의된 값을 안전하게 가져올 수 있습니다.
    // app.module.ts (TypeORM 설정 예시)
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get<string>('DB_HOST'),
        password: configService.get<string>('DB_PASSWORD'),
        // ...
      }),
    }),

📌 요약

  • NestJS의 파이프(Pipe)는 컨트롤러로 들어오는 데이터를 변환하거나 유효성을 검사하는 미들웨어입니다.
  • class-validatorValidationPipe를 함께 사용하면, DTO 클래스에 데코레이터를 붙이는 것만으로 선언적이고 강력한 유효성 검증을 전역적으로 적용할 수 있습니다.
  • @nestjs/config 모듈은 .env 파일을 통해 환경 변수를 관리하는 표준적인 방법을 제공합니다.
  • ConfigService를 주입받아 get() 메서드를 사용하면, 코드에서 민감한 설정 값을 분리하여 애플리케이션의 보안과 유연성을 크게 향상시킬 수 있습니다.

0개의 댓글