16. Module reference

Nest는 내부 공급자 목록을 탐색하고 주입 토큰을 조회 키로 사용하여 공급자에 대한 참조를 얻을 수 있는 ModuleRef  클래스를 제공한다. 또한 이 ModuleRe f클래스는 정적 공급자와 범위가 지정된 공급자를 모두 동적으로 인스턴스화하는 방법을 제공한다. ModuleRef 는 일반적인 방법으로 클래스에 주입할 수 있다.

// cats.servicee.ts

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

힌트) ModuleRef 클래스는 @nestjs/core 패키지에서 가져온다.

 

인스턴스 검색

ModuleRef 인스턴스 (이하 모듈 참조 라고 함 ) 에는 get()메서드가 있다. 이 메소드는 주입 토큰/클래스 이름을 사용하여 현재 모듈에 존재하는(인스턴스화된) 공급자, 컨트롤러 또는 주입 가능 항목(예: 가드, 인터셉터 등)을 검색한다.

// cats.service.ts

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

  onModuleInit() {
    this.service = this.moduleRef.get(Service);
  }
}

주의)  get() 메서드를 사용하여 범위가 지정된 공급자(일시적 또는 요청 범위)를 검색할 수 없다. 대신 아래에 설명된 기술을 사용해야 한다. 여기에서 범위를 제어하는 ​​방법을 알아볼 수 있다.

 

전역 컨텍스트에서 공급자를 검색하려면(예: 공급자가 다른 모듈에 삽입된 경우) 해당 { strict: false }옵션을  get() 에 두 번째 인수로 전달한다.

this.moduleRef.get(Service, { strict: false });

 

범위가 지정된 공급자 확인 

범위가 지정된 공급자(일시적 또는 요청 범위)를 동적으로 확인하려면 공급자의 주입 토큰을 인수로 전달하는 resolve() 메서드를 사용한다.

// cats.service.ts

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

  async onModuleInit() {
    this.transientService = await this.moduleRef.resolve(TransientService);
  }
}

이 resolve() 메서드는 자체 DI 컨테이너 하위 트리에서 공급자의 고유 인스턴스를 반환한다 . 각 하위 트리에는 고유한 컨텍스트 식별자가 있다. 따라서 이 메서드를 두 번 이상 호출하고 인스턴스 참조를 비교하면 동일하지 않음을 알 수 있다.

// cats.service.ts

@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() 호출에서 단일 인스턴스를 생성 하고 동일한 생성된 DI 컨테이너 하위 트리를 공유하는지 확인하려면 컨텍스트 식별자를 resolve() 메서드에 전달할 수 있다. 클래스를 사용하여 ContextIdFactory컨텍스트 식별자를 생성한다. 이 클래스는 적절한 고유 식별자를 반환하는 create() 메서드를 제공한다.

// cats.service.ts

@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
  }
}

힌트) ContextIdFactory 클래스는 @nestjs/core 에서 가져온다.

 

REQUEST 공급자 등록

수동으로 생성된 컨텍스트 식별자( ContextIdFactory.create() 로 생성된 )는 Nest 종속성 주입 시스템에 의해 인스턴스화 되지 않은(undefined) 혹은 관리되지 않는 DI 하위 트리를 나타낸다.

사용자 정의 REQUEST 개체를 수동으로 생성된 DI 하위 트리에 등록하려면 다음과 같은이 ModuleRef#registerRequestByContextId() 메서드를 사용한다.

 

const contextId = ContextIdFactory.create();
this.moduleRef.registerRequestByContextId(/* YOUR_REQUEST_OBJECT */, contextId);

현재 하위 트리 가져오기

경우에 따라 요청 컨텍스트 내에서 요청 범위 공급자의 인스턴스를 확인하고 싶을 수도 있다. CatsService 가 요청 범위이고 동일학게 요청 범위 공급자 표시된 CatsRepository  인스턴스를 확인하려고 한다고 가정해 보겠다 . 동일한 DI 컨테이너 하위 트리를 공유하려면 새 컨텍스트 식별자를 생성하는 대신(예: ContextIdFactory.create() 함수를 사용하여) 현재 컨텍스트 식별자를 얻어야 한다. 현재 컨텍스트 식별자를 얻으려면  @Inject() 데코레이터를 사용하여 요청 객체를 주입하는 것부터 시작해야 한다.

// cats.service.ts

@Injectable()
export class CatsService {
  constructor(
    @Inject(REQUEST) private request: Record<string, unknown>,
  ) {}
}

이제 ContextIdFactoryd 클래스의  getByRequest() 메소드를 사용하여 요청 객체를 기반으로 컨텍스트 ID를 생성하고 이를  resolve() 호출에 전달한다.

const contextId = ContextIdFactory.getByRequest(this.request);
const catsRepository = await this.moduleRef.resolve(CatsRepository, contextId);

 

사용자 정의 클래스를 동적으로 인스턴스화

이전에 공급자  등록되지 않은 클래스를 동적으로 인스턴스화하려면 모듈 참조의 create() 메서드를 사용한다.

// cats.service.ts

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

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

'Backend(Framework) > NestJS 개요(공식문서 번역)' 카테고리의 다른 글

18. Execution context  (1) 2023.12.02
17. Lazy-loading modules  (1) 2023.12.02
15. Circular Dependency  (1) 2023.12.02
14. Injection scopes  (1) 2023.12.02
13. Dynamic modules  (1) 2023.12.02
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유