Injection scopes

Injection scopes

다른 언어를 사용하는 사람들에게는 Nest에서 거의 모든 것이 들어오는 요청에서 공유되는 것이 어색할 수 있습니다. 우리는 데이터베이스에 대한 연결 풀, 전역 상태등의 싱글 톤 서비스를 가지고 있습니다. 일반적으로 Node.js는 모든 요청이 별도의 스레드에 의해 처리되는 요청/응답 다중 스레드 상태 비 저장 모델을 따르지 않습니다. 따라서 싱글 톤 인스턴스를 사용하는 것은 애플리케이션에 안전합니다.

그러나 컨트롤러의 요청 기반 수명이 의도적인 동작 (예: GraphQL 애플리케이션의 요청별 캐시, 요청 추적 또는 다중 테넌시) 일 수 있는 경우가 있습니다. 어떻게 처리 할 수 있습니까?

Scopes

기본적으로 모든 공급자는 싱글 톤으로 작동하고 요청 범위를 설정하며 임시 모드로 전환 할 수 있습니다. 차이점을 이해하려면 다음 표를 참조하십시오.

SINGLETON

각 공급자는 여러 클래스에서 공유할 수 있습니다. 공급자 수명은 응용 프로그램 수명주기와 밀접한 관련이 있습니다. 응용 프로그램이 부트 스트랩되면 모든 공급자가 이미 인스턴스화됩니다. 싱글 톤 범위가 기본적으로 사용됩니다.

REQUEST

요청 처리가 완료된 후 수신되는 모든 요청및 가비지에 대해 제공자의 새 인스턴스가 독점적으로 작성됩니다.

TRANSIENT

일시적인 제공자는 제공자간에 공유 할 수 없습니다. 다른 공급자가 Nest 컨테이너에 특정 임시 공급자를 요청할 때마다 컨테이너는 새로운 전용 인스턴스를 만듭니다.

info 힌트 싱글 톤 스코프를 사용하는 것이 항상 권장되는 방법입니다. 요청간에 공급자를 공유하면 메모리 소비가 줄어들어 애플리케이션 성능이 향상됩니다 (매번 클래스를 인스턴스화하지 않아도 됨).

Usage

다른 주입 범위로 전환하려면@Injectable()데코레이터에 인수를 전달해야 합니다.

import { Injectable, Scope } from '@nestjs/common';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {}

custom provider의 경우 추가scope 속성을 설정해야합니다.

{
  provide: 'CACHE_MANAGER',
  useClass: CacheManager,
  scope: Scope.TRANSIENT,
}

컨트롤러에 관해서는 ControllerOptions 객체를 전달하십시오 :

@Controller({
  path: 'cats',
  scope: Scope.REQUEST,
})
export class CatsController {}

warning 알림 게이트웨이는 단일 범위 역할을 하므로 요청 범위 공급자에 의존해서는 안됩니다. 하나의 게이트웨이는 내부의 실제 소켓을 캡슐화하며 여러번 인스턴스화 할 수 없습니다.

Per-request injection

요청 범위의 공급자는 매우 신중하게 사용해야합니다. 스코프는 인젝션 체인에서 실제로 버블링됨을 명심하십시오. 컨트롤러가 요청 범위의 공급자에 의존하는 경우 컨트롤러도 실제로 요청 범위입니다.

CatsController<-CatsService<-CatsRepository 체인을 상상해 보십시오. CatsService가 요청 범위 (및 나머지는 이론적으로 싱글 톤) 인 경우, CatsController도 요청 범위가 됩니다 (요청 범위가 지정된 인스턴스는 새로 작성된 컨트롤러에 삽입되어야하기 때문에). 반면에 CatsRepository는 싱글 톤으로 남아 있을 것입니다.

경고 이 경우 순환 종속성은 매우 고통스러운 부작용으로 이어질 수 있으므로 부작용을 일으키지 않아야 합니다.

Request provider

HTTP 애플리케이션에서 요청 범위 제공자를 사용하면 원래 요청 참조를 삽입 할 수 있습니다.

import { Injectable, Scope, Inject } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {
  constructor(@Inject(REQUEST) private readonly request: Request) {}
}

그러나 이 기능은 마이크로 서비스 또는 GraphQL 응용 프로그램에서는 작동하지 않습니다. GraphQL 애플리케이션에서 대신 CONTEXT를 삽입 할 수 있습니다.

import { Injectable, Scope, Inject } from '@nestjs/common';
import { CONTEXT } from '@nestjs/graphql';

@Injectable({ scope: Scope.REQUEST })
export class CatsService {
  constructor(@Inject(CONTEXT) private readonly context) {}
}

그런 다음 context 값 (GraphQLModule)을 구성하여 request를 특성으로 포함할 수 있습니다.

Performance

요청 범위 공급자를 사용하면 분명히 응용 프로그램 성능에 영향을 미칩니다. Nest가 가능한 한 많은 메타 데이터를 캐시하려고 시도하더라도 각 요청마다 클래스의 인스턴스를 작성해야 합니다. 따라서 평균 응답 시간과 전반적인 벤치마킹 결과가 느려집니다. 공급자가 반드시 요청 범위를 지정할 필요가 없다면 싱글 톤 범위를 고수해야합니다.

Last updated