nestjs Module reference

adam2·2022년 10월 4일

ModuleRef

  • 내부 provider 리스트와 provider의 injection token을 조회 키로 사용해 provider에 대한 reference를 얻는데 사용
  • ModuleRef를 이용해 static provider와 scoped provider를 동적으로 인스턴스화 할 수 있다.
  1. 인스턴스 검색
    ModuleRef.get()를 이용해서 모듈에서 사용중인 인스턴스화된 provider, controller, injectable한 객체(guard, interceptor)를 검색할 수 있다.
@Injectable()
export class CatsService implements OnModuleInit {
  private service: Service;
  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    this.service = this.moduleRef.get(Service);
  }
}
  1. scoped provider를 resolve
    ModuleRef.resolve()를 이용해 동적으로 scoped provider를 만들 수 있다.
    resolve() 함수는 자체 DI container sub-tree에서 고유한 인스턴스를 반환한다.
    각각의 sub-tree는 고유한 context identifier를 가지고 있다. 그래서 이 함수를 한번 이상 호출해 instance reference를 비교해보면, 두개의 인스턴스가 서로 다른 것을 확인할 수 있다.
@Injectable()
export class CatsService implements OnModuleInit {
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    const transientServices = await Promise.all([
      this.moduleRef.resolve(TransientService),
      this.moduleRef.resolve(TransientService),
    ]);
    console.log(transientServices[0] === transientServices[1]); // false. 서로 다른 인스턴스
  }
}

여러번 resolve()를 호출해도 하나의 instance를 얻고싶다면, resolve()함수에 ContextIdFactory를 사용해 context identifier를 넘겨줘야 한다.

@Injectable()
export class CatsService implements OnModuleInit {
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    const contextId = ContextIdFactory.create();
    const transientServices = await Promise.all([
      this.moduleRef.resolve(TransientService, contextId),
      this.moduleRef.resolve(TransientService, contextId),
    ]);
    console.log(transientServices[0] === transientServices[1]); // true
  }
}
  1. 동적으로 커스텀한 클래스를 인스턴스화 할 때
    provider로 등록되지 않은 클래스를 동적으로 인스턴스화할 때, create()함수를 사용한다.
@Injectable()
export class CatsService implements OnModuleInit {
  private catsFactory: CatsFactory;
  constructor(private moduleRef: ModuleRef) {}

  async onModuleInit() {
    this.catsFactory = await this.moduleRef.create(CatsFactory);
  }
}

0개의 댓글