17. Lazy-loading modules

기본적으로 모듈은 즉시 로드됩니다. 즉, 애플리케이션이 로드되자마자 즉시 필요한지 여부에 관계없이 모든 모듈도 로드e된다. 이는 대부분의 애플리케이션에는 문제가 없지만 시작 대기 시간("콜드 스타트")이 중요한 서버리스 환경 에서 실행되는 앱/작업자에게는 병목 현상이 발생할 수 있다.

 

지연 로딩은 특정 서버리스 함수 호출에 필요한 모듈만 로드하여 부트스트랩 시간을 줄이는 데 도움이 된다. 또한 서버리스 기능이 "웜"되면 다른 모듈을 비동기식으로 로드하여 후속 호출에 대한 부트스트랩 시간을 더욱 단축할 수도 있다(지연된 모듈 등록).

 

주의) 지연 로드된 모듈 및 서비스에서는 수명 주기 후크 메서드가 호출되지 않는다 .

 

시작하기

주문형 모듈을 로드하기 위해 Nest는 일반적인 방법으로 클래스에 삽입할 수 있는 LazyModuleLoader 클래스를 제공한다.

//cats.service.ts

@Injectable()
export class CatsService {
  constructor(private lazyModuleLoader: LazyModuleLoader) {}
}

힌트) LazyModuleLoader 는 @nestjs/core 패키지에서 불러옵니다.

 

또는 다음과 같이 애플리케이션 부트스트랩 파일( main.ts ) 내에서 LazyModuleLoader 공급자에 대한 참조를 얻을 수 있다 .

// "app" represents a Nest application instance
const lazyModuleLoader = app.get(LazyModuleLoader);

이를 사용하면 이제 다음 구성을 사용하여 모든 모듈을 로드할 수 있다.

const { LazyModule } = await import('./lazy.module');
const moduleRef = await this.lazyModuleLoader.load(() => LazyModule);

힌트) "지연 로드" 모듈은 첫 번째로  LazyModuleLoader#load 메서드 호출 시 캐시된다 . 즉, 연속적인 로드 시도는 매우 빠르며 LazyModule 모듈 을 다시 로드하는 대신 캐시된 인스턴스를 반환다.

Load "LazyModule" attempt: 1
time: 2.379ms
Load "LazyModule" attempt: 2
time: 0.294ms
Load "LazyModule" attempt: 3
time: 0.303ms

또한 "지연 로드" 모듈은 애플리케이션 부트스트랩에 즉시 로드된 모듈 및 나중에 앱에 등록된 다른 지연 모듈과 동일한 모듈 그래프를 공유한다.

 

일반 Nest 모듈을 내보내는  lazy.module.ts TypeScript 파일은 어디에 있을까? (추가 변경이 필요하지 않음)

 

LazyModuleLoader#load 메서드는 내부 공급자 목록을 탐색하고 주입 토큰을 조회 키로 사용하여 공급자에 대한 참조를 얻을 수 있는 모듈 참조 ( LazyModule 의 ) 를 반환한다.

 

LazyModule예를 들어, 다음과 같은 정의를 가진 a가 있다고 가정해 보자.

@Module({
  providers: [LazyService],
  exports: [LazyService],
})
export class LazyModule {}

힌트) 지연 로드된 모듈은 전혀 의미가 없기 때문에 전역 모듈 로 등록할 수 없다(모든 정적으로 등록된 모듈이 이미 인스턴스화되었을 때 요청 시 지연 등록되기 때문다). 마찬가지로 등록된 전역 인핸서 (가드/인터셉터/등)도 제대로 작동하지 않는다 .

const { LazyModule } = await import('./lazy.module');
const moduleRef = await this.lazyModuleLoader.load(() => LazyModule);

const { LazyService } = await import('./lazy.service');
const lazyService = moduleRef.get(LazyService);

주의) Webpack을 사용하는 경우 tsconfig.json 파일을 업데이트해야 한다. compilerOptions.module  속성 값은  "esnext"하고  compilerOptions.moduleResolution 값에는 "node" 를  추가합니다 .

{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "node",
    ...
  }
}

이러한 옵션을 설정하면 코드 분할 기능을 활용할 수 있다.

 

지연 로딩 컨트롤러, 게이트웨이 및 리졸버

Nest의 컨트롤러(또는 GraphQL 애플리케이션의 리졸버)는 경로/경로/주제(또는 쿼리/변형) 세트를 나타내기 때문에 LazyModuleLoader 클래스를 사용하여 지연 로드할 수 없다.

 

예를 들어, 내부적으로 (  @nestjs/platform-fastify 패키지를 사용하여) Fastify 드라이버를 사용하여 REST API(HTTP 애플리케이션)를 구축한다고 가정해 보자. Fastify에서는 애플리케이션이 준비되거나 메시지를 성공적으로 수신한 후에 경로를 등록할 수 없다. 이는 모듈 컨트롤러에 등록된 경로 매핑을 분석하더라도 런타임에 등록할 방법이 없기 때문에 지연 로드된 모든 경로에 액세스할 수 없다는 의미이다.

 

마찬가지로 우리가  @nestjs/microservices 패키지의 일부로 제공하는 일부 전송 전략 (Kafka, gRPC 또는 RabbitMQ 포함) 에서는 연결이 설정되기 전에 특정 주제/채널을 구독/수신해야 한다. 애플리케이션이 메시지 수신을 시작하면 프레임워크는 새 주제를 구독/수신할 수 없다.

 

마지막으로, 코드 우선 접근 방식이 활성화된 @nestjs/graphql 패키지는 메타데이터를 기반으로 GraphQL 스키마를 즉석에서 자동으로 생성한다. 즉, 모든 클래스를 미리 로드해야 한다. 그렇지 않으면 적절하고 유효한 스키마를 생성할 수 없다.

 

일반적인 사용 사례 

가장 일반적으로 작업자/크론 작업/람다 및 서버리스 함수/웹후크가 입력 인수(경로 경로/날짜/쿼리 매개변수 등)를 기반으로 다른 서비스(다른 로직)를 트리거해야 하는 상황에서 지연 로드 모듈을 볼 수 있다. 반면, 지연 로딩 모듈은 시작 시간이 그다지 중요하지 않은 모놀리식 애플리케이션에는 그다지 적합하지 않을 수 있다.

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

19. 수명 주기 이벤트  (0) 2023.12.03
18. Execution context  (1) 2023.12.02
16. Module reference  (1) 2023.12.02
15. Circular Dependency  (1) 2023.12.02
14. Injection scopes  (1) 2023.12.02
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유