본문 바로가기
개발/NestJS

[NestJS] 의존성 주입의 모든 것: Provider와 useClass, useFactory, useValue 사용법

by coking 2024. 10. 23.

최근 DDD 개발을 진행중에 있는데 생각보다 이 개념을 디테일하게 설명해주는 글을 찾기 쉽지 않고 사용법을 제대로 알지 못하고 그냥 복사 붙이기해서 사용하는 사람들이 있어서 작성하게 됐다!

NestJS에서 useClass, useFactory, useValue의 차이와 용도

NestJS에서 의존성 주입(Dependency Injection)을 위해 제공하는 useClass, useFactory, useValueproviders 설정에서 사용되는 여러 방법들이다. 각각의 방법은 서비스나 값을 주입하기 위해 사용하는 방식이 조금씩 다르다. 이들이 어떻게 다른지와 각자의 용도를 설명하고, 실제로 사용되는 방법까지 예시를 통해 알아보자!

1. useClass 사용 예시

useClass특정 클래스를 주입하고, 다른 클래스나 서비스에서 이를 주입받아 사용하는 방법입니다. 아래 예시에서 LoggerService 대신 CustomLoggerService를 주입하고 사용합니다.

코드 예시

서비스 정의 (logger.service.ts)
export class LoggerService {
  log(message: string) {
    console.log('Log:', message);
  }
}

export class CustomLoggerService {
  log(message: string) {
    console.log('Custom Log:', message);
  }
}
모듈 설정 (app.module.ts)
import { Module } from '@nestjs/common';
import { LoggerService, CustomLoggerService } from './logger.service';
import { AppService } from './app.service';

@Module({
  providers: [
    AppService,
    {
      provide: LoggerService,
      useClass: CustomLoggerService, // LoggerService 대신 CustomLoggerService를 주입
    },
  ],
})
export class AppModule {}
서비스 사용 (app.service.ts)
import { Injectable } from '@nestjs/common';
import { LoggerService } from './logger.service';

@Injectable()
export class AppService {
  constructor(private readonly logger: LoggerService) {}

  performTask() {
    this.logger.log('Performing a task'); // CustomLoggerService의 log 메서드가 호출됨
  }
}
실행 시 로그 출력
Custom Log: Performing a task
  • AppService에서 LoggerService를 주입받고 있지만, 실제로는 CustomLoggerService의 인스턴스가 주입되기 때문에 Custom Log: Performing a task가 출력됩니다.

2. useFactory 사용 예시

useFactory동적으로 의존성을 생성하여 주입하는 방법입니다. 이 방법을 통해 의존성을 생성할 때 환경 변수나 외부 설정에 따라 다르게 처리할 수 있습니다.

코드 예시

서비스 정의 (logger.service.ts)
export class LoggerService {
  constructor(private readonly prefix: string) {}

  log(message: string) {
    console.log(`${this.prefix}: ${message}`);
  }
}
모듈 설정 (app.module.ts)
import { Module } from '@nestjs/common';
import { LoggerService } from './logger.service';
import { AppService } from './app.service';

@Module({
  providers: [
    AppService,
    {
      provide: LoggerService,
      useFactory: () => {
        const prefix = process.env.LOG_PREFIX || 'DefaultPrefix';
        return new LoggerService(prefix); // 동적으로 LoggerService 인스턴스 생성
      },
    },
  ],
})
export class AppModule {}
서비스 사용 (app.service.ts)
import { Injectable } from '@nestjs/common';
import { LoggerService } from './logger.service';

@Injectable()
export class AppService {
  constructor(private readonly logger: LoggerService) {}

  performTask() {
    this.logger.log('Performing a task'); // 환경 변수에 따라 다른 prefix가 사용됨
  }
}
실행 시 로그 출력 (환경 변수 LOG_PREFIX에 따라 다름)
DefaultPrefix: Performing a task
  • 만약 환경 변수 LOG_PREFIX가 설정되지 않았다면, 기본값인 "DefaultPrefix"가 사용됩니다.
  • useFactory를 통해 동적으로 인스턴스를 생성하면서, 설정에 따라 로그의 접두사를 달리합니다.

3. useValue 사용 예시

useValue특정 값이나 객체를 직접 제공하여 주입하는 방법입니다. 주로 상수, 설정 객체 또는 테스트용 Mock 객체를 주입할 때 사용됩니다.

코드 예시

Mock 객체 정의
const MOCK_LOGGER = {
  log: (message: string) => console.log('Mock Log:', message),
};
모듈 설정 (app.module.ts)
import { Module } from '@nestjs/common';
import { AppService } from './app.service';

@Module({
  providers: [
    AppService,
    {
      provide: 'LoggerService',
      useValue: MOCK_LOGGER, // 특정 값(객체)을 직접 제공
    },
  ],
})
export class AppModule {}
서비스 사용 (app.service.ts)
import { Injectable, Inject } from '@nestjs/common';

@Injectable()
export class AppService {
  constructor(
    @Inject('LoggerService') private readonly logger: { log: (message: string) => void },
  ) {}

  performTask() {
    this.logger.log('Performing a task'); // MOCK_LOGGER의 log 메서드 호출
  }
}
실행 시 로그 출력
Mock Log: Performing a task
  • MOCK_LOGGER 객체가 LoggerService로 제공되었기 때문에, Mock Log: Performing a task가 출력됩니다.
  • 테스트 환경이나 간단한 상수 제공에 유용하게 사용됩니다.

요약

제공 방식 설명 사용 예시 사용 결과
useClass 특정 클래스를 사용하여 의존성 주입 useClass: CustomLoggerService 요청한 클래스 대신 CustomLoggerService가 주입됨
useFactory 팩토리 함수로 동적 생성 및 설정 useFactory: () => new LoggerService 환경 변수 등 설정에 따라 동적으로 인스턴스 생성
useValue 특정 값이나 객체를 직접 주입 useValue: MOCK_LOGGER 고정된 값 또는 Mock 객체가 주입됨

댓글