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
Was this helpful?