# Caching

## Caching

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

## Installation

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

```bash
$ npm install --save cache-manager
```

## In-memory cache

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

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

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

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

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

> warning **경고** `GET` 엔드 포인트만 캐시됩니다. 또한 원시 응답 오브젝트 (`@Res()`)를 주입하는 HTTP 서버 라우트는 캐시 인터셉터를 사용할 수 없습니다. 자세한 내용은  [응답 매핑](https://docs.nestjs.com/interceptors#response-mapping)을 참조하십시오.

## Global cache

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

```typescript
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`를 적용할 수도 있습니다 (사용중인 전송 방법에 관계없이).

```typescript
@@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()`메서드에 전달하십시오.

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

## Different stores

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

```typescript
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()`메소드를 대체하십시오.

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

## Async configuration

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

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

```typescript
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`).

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

Alternatively, you can use the `useClass` method:

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

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

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

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

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jakekwak.gitbook.io/nestjs/techniques/caching.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
