배꼽파지 않도록 잘 개발해요

[NestJS] 문자열을 사용한 NestJS 의존성 주입시 주의할 점 본문

BackEnd/Express / NestJS

[NestJS] 문자열을 사용한 NestJS 의존성 주입시 주의할 점

꼽파 2024. 8. 26. 05:57

데이터베이스와의 연결 여부를 알 수 있는 healthcheck API를 만들다가 다음과 같은 오류가 발생하였다.

 

 

Error: Nest can't resolve dependencies of the HealthCheckService (REDIS_CLIENT, ?). Please make sure that the argument default at index [1] is available in the HealthCheckModule context.

Potential solutions:
- Is HealthCheckModule a valid NestJS module?
- If default is a provider, is it part of the current HealthCheckModule?      
- If default is exported from a separate @Module, is that module imported within HealthCheckModule?
  @Module({
    imports: [ /* the Module containing default */ ]
  })

 

NestJS의 의존성 주입 시스템에서 문자열을 사용하여 프로바이더를 등록하고 주입할 때 주의해야 할 점은, 프로바이더를 등록할 때 사용한 문자열과 주입할 때 사용하는 문자열이 정확히 일치해야 한다는 것이다.

 

import { Module, Global } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import Redis from 'ioredis';
import { IRedisOptions } from "./interfaces";

@Global()
@Module({
    imports: [ConfigModule],
    providers: [{
        provide: 'REDIS_CLIENT',
        useFactory: (configService: ConfigService) => {
            const host = configService.get<string>('REDIS_HOST')
            const port = configService.get<number>('REDIS_PORT');
            const password = configService.get<string>('REDIS_PASSWORD');

            const redisOptions: IRedisOptions = {
                host,
                port,
                password,
            }

            return new Redis(redisOptions);
        },
        inject: [ConfigService]
    }],
        exports: ['REDIS_CLIENT'],
})
export class RedisModule {}

예를 들어, RedisModule에서 provide: 'REDIS_CLIENT'로 Redis 클라이언트를 등록한 경우, 다른 모듈에서 이를 주입받으려면 반드시 'REDIS_CLIENT'라는 문자열을 사용해야 한다. 문자열이 일치하지 않으면 NestJS는 해당 프로바이더를 찾지 못하여 오류를 발생시킨다.

 

이런식으로 찾지 못해서 오류가 난다.


해결 방법

  1. module에 DataSource를 직접 생성하여 provider로 직접 'DATA_SOURCE'라는 문자열을 등록한다.
  2. @inject(DataSource) private readonly dataSource: DataSource라고 쓴다.
  3. private readonly dataSource: DataSource로 @Inject없이 직접 주입한다.

 

1. module에 provider로 직접 등록하기

@Module({
  imports: [ConfigModule],
  providers: [
    {
      provide: 'DATA_SOURCE',
      useFactory: async (configService: ConfigService) => {
        const config = getTypeOrmConfig(configService);
        const dataSource = new DataSource(config);

        await dataSource.initialize();
        return dataSource;
      },
      inject: [ConfigService],
    },
  ],
  exports: ['DATA_SOURCE'],
})
export class DatabaseModule {}

 

https://velog.io/@nuri00/Nest.js-typeorm%EC%9C%BC%EB%A1%9C-DB-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0

 

Nest.js typeorm으로 DB 연결하기

지난 포스팅에서는 Nest.js 모듈 생성하는 방법과 라우팅하는 방식을 설명했다. 지난 포스팅이번 포스팅에서는 본격적으로 CRUD 구현을 하기 전 DB에 연결하는 코드를 설명해보려고 한다. 본인은 po

velog.io

 

위 글 작성자도 모듈 내에서 DataSource를 생성한 후 provider 설정을 별도로 해주었다.

 

2. @inject(DataSource) private readonly dataSource: DataSource라고 쓴다.

 

3. private readonly dataSource: DataSource로 @Inject없이 직접 주입한다.

TypeOrm 모듈 설정이 제대로 되어 있으면 직접 주입 받을 수 있다.

코드가 간결한 3번으로 해결하였다. 서비스 단에서 DataSource를 주입할 곳이 여기밖에 없을 것 같아서이다.

 

위의 방법 중 한 가지로 수정하면 이렇게 잘 작동한다.

728x90