Caching

Caching

캐싱은 앱의 성능을 향상시키는 데 도움이되는 훌륭하고 간단한 기술입니다. 고성능 데이터 액세스를 제공하는 임시 데이터 저장소 역할을합니다.

Installation

먼저 필요한 패키지를 설치하십시오.

$ npm install --save cache-manager

In-memory cache

Nest는 다양한 캐시 스토리지 제공자를 위한 통합 API를 제공합니다. 내장된 것은 인 메모리 데이터 저장소입니다. 그러나 Redis와 같은 보다 포괄적인 솔루션으로 쉽게 전환할 수 있습니다. 캐싱을 활성화하려면 먼저 CacheModule을 가져 와서 register() 메소드를 호출하십시오.

import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';

@Module({
  imports: [CacheModule.register()],
  controllers: [AppController],
})
export class ApplicationModule {}

그런 다음 데이터를 캐시할 위치에 CacheInterceptor를 연결하십시오.

@Controller()
@UseInterceptors(CacheInterceptor)
export class AppController {
  @Get()
  findAll(): string[] {
    return [];
  }
}

warning 경고 GET 엔드 포인트만 캐시됩니다. 또한 원시 응답 오브젝트 (@Res())를 주입하는 HTTP 서버 라우트는 캐시 인터셉터를 사용할 수 없습니다. 자세한 내용은 응답 매핑을 참조하십시오.

Global cache

필요한 상용구의 양을 줄이려면 CacheInterceptor를 전역으로 모든 엔드 포인트에 바인딩 할 수 있습니다.

import { CacheModule, Module, CacheInterceptor } from '@nestjs/common';
import { AppController } from './app.controller';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
  imports: [CacheModule.register()],
  controllers: [AppController],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: CacheInterceptor,
    },
  ],
})
export class ApplicationModule {}

WebSockets & Microservices

MicroService의 패턴뿐만 아니라 WebSocket 가입자에게 CacheInterceptor를 적용할 수도 있습니다 (사용중인 전송 방법에 관계없이).

@@filename()
@CacheKey('events')
@UseInterceptors(CacheInterceptor)
@SubscribeMessage('events')
handleEvent(client: Client, data: string[]): Observable<string[]> {
  return [];
}
@@switch
@CacheKey('events')
@UseInterceptors(CacheInterceptor)
@SubscribeMessage('events')
handleEvent(client, data) {
  return [];
}

info 힌트 @CacheKey()데코레이터는 @nestjs/common 패키지에서 가져옵니다.

그러나 캐시된 데이터를 저장하고 검색하는 데 사용되는 키를 지정하려면 추가@CacheKey()데코레이터가 필요합니다. 또한 모든 것을 캐시하지 않아야합니다. 단순히 데이터를 쿼리하지 않고 일부 비즈니스 작업을 수행하는 작업은 캐시되지 않아야 합니다.

Customize caching

캐시된 모든 데이터에는 자체 TTL (만료 시간)이 있습니다. 기본값을 사용자 정의하려면 options 객체를 register()메서드에 전달하십시오.

CacheModule.register({
  ttl: 5, // seconds
  max: 10, // maximum number of items in cache
});

Different stores

이 서비스는 후드에서 cache-manager를 활용합니다. cache-manager 패키지는 Redis와 같은 다양한 유용한 저장소를 지원합니다. 지원되는 전체 저장소 목록은 여기에서 확인할 수 있습니다. Redis 스토어를 설정하려면 해당 옵션과 함께 패키지를 register()메소드에 전달하면 됩니다.

import * as redisStore from 'cache-manager-redis-store';
import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';

@Module({
  imports: [
    CacheModule.register({
      store: redisStore,
      host: 'localhost',
      port: 6379,
    }),
  ],
  controllers: [AppController],
})
export class ApplicationModule {}

Adjust tracking

기본적으로 Nest는 요청 URL (HTTP 앱) 또는 캐시 키 (웹 소켓 및 마이크로 서비스 앱, @CacheKey()데코레이터를 통해 설정)를 사용하여 캐시 레코드를 엔드 포인트와 연결합니다. 그럼에도 불구하고 때로는 HTTP 헤더 (예: profile 엔드 포인트를 올바르게 식별하기위한 Authorization)를 사용하는 등 다양한 요소를 기반으로 추적을 설정하고자 할 수 있습니다.

이를 위해 CacheInterceptor의 서브 클래스를 작성하고 trackBy()메소드를 대체하십시오.

@Injectable()
class HttpCacheInterceptor extends CacheInterceptor {
  trackBy(context: ExecutionContext): string | undefined {
    return 'key';
  }
}

Async configuration

컴파일시 정적으로 전달하는 대신 모듈 옵션을 비동기적으로 전달할 수 있습니다. 이 경우 비동기 구성을 처리하는 몇 가지 방법을 제공하는 registerAsync() 메소드를 사용하십시오.

한 가지 방법은 팩토리 기능을 사용하는 것입니다.

CacheModule.registerAsync({
  useFactory: () => ({
    ttl: 5,
  }),
});

Our factory behaves like all other asynchronous module factories (it can be async and is able to inject dependencies through inject).

CacheModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    ttl: configService.getString('CACHE_TTL'),
  }),
  inject: [ConfigService],
});

Alternatively, you can use the useClass method:

CacheModule.registerAsync({
  useClass: CacheConfigService,
});

위의 구성은 CacheModule내에서 CacheConfigService를 인스턴스화하여 옵션 객체를 얻는 데 사용합니다. CacheConfigService는 설정 옵션을 제공하기 위해 CacheOptionsFactory 인터페이스를 구현해야 합니다:

@Injectable()
class CacheConfigService implements CacheOptionsFactory {
  createCacheOptions(): CacheModuleOptions {
    return {
      ttl: 5,
    };
  }
}

다른 모듈에서 가져온 기존 구성 공급자를 사용하려면 useExisting 구문을 사용하십시오.

CacheModule.registerAsync({
  imports: [ConfigModule],
  useExisting: ConfigService,
});

이것은 useClass와 동일하게 작동하며 한 가지 중요한 차이점이 있습니다. CacheModule은 가져온 모듈을 찾아서 자체적으로 인스턴스화 하는 대신 이미 작성된 ConfigService를 재사용합니다.

Last updated