Nest.js 탐험기3 - cache를 써보자

2021. 1. 20. 23:11개발/Node & Javascript

728x90
반응형

1. 개요

  • 우리가 개발을 할 때, 가장 친숙하게 쓰이는 것이 cache module이 아닐까 생각해본다.
  • 이 때, Cache module을 어떻게 nest.js에서 사용할 수 있을지 체크해보자
  • 본 문서는 redis 기준으로 작성하였고, 따로 호환성을 고려하지 않고 작성해서 latest version으로 작성했다고 보면 된다.

2. 실습 환경

2.1. Redis를 docker container 셋팅

  • 이미 docker 환경이 setup되어 있다면 아래와 같은 명령어를 통해 docker container를 띄우자.
# run
docker run --name redis-test -p 6379:6379 -d redis:alpine

# 나중에 container 죽일 때 쓰면 된다.
# kill container
docker kill redis-test

2.2. Nest.js 환경 셋팅

  • Nest.js 기본 셋팅은 공식 홈페이지를 참조하여 셋팅하도록 하자.

2.3. Cache module setup

  • 기본적으로 Nest.js에서는 cache manager를 통해서 cache를 활용할 수 있게 되어있다.
  • 아래와 같이 cache-manager를 설치해주도록 하자.
  • 그리고 multi store 중에서 ioredis cache manager를 설치하자.
yarn add cache-manager
yarn add @types/cache-manager --dev

yarn add cache-manager-ioredis

3. 실습

3.1. Module Import

  • 우선 module에 cache module을 만들어서 넣어주어야 한다.
  • 아래와 같이 cache module을 등록해준다.
import * as redisStore from 'cache-manager-ioredis';

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

3.2. Cache 이용

  • 크게 global로 interceptor를 등록하거나 controller, handler쪽에서 annotation을 활용하거나, cacheManager를 통한 접근으로 사용 가능하다.

3.2.1. global로 적용

  • 아마 안 그러겠지만 global로 적용 시키고 싶을 때가 있다. 그럴 경우에는 모듈 전체에 cacheInterceptor를 등록할 수 있다.
@Module({
  imports: [
    ...
  ],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: CacheInterceptor,
    },
  ],

3.2.2. controller에 적용

  • 아래와 같이 controller level에서도 적용이 가능하다.
@UseInterceptors(CacheInterceptor)
export class AppController {
  ...
}

3.2.3 handler level로 적용

  • 아래와 같이 handler 단위로 적용 가능하다.
  • 주의할 점은 일반 method에는 적용이 안되고, handler에만 적용이 가능하다.
@CacheKey('malgogi')
@CacheTTL(20)
@Get('/cache')
async findAll(): Promise<string[]> {
  console.log('not cached');
  return ['a', 'b', 'c'];
}

3.2.4 manager 사용

  • 아래와 같이 cacheManager를 직접 inject 받아서 사용할 수 있다.
  • 주의할 점은 Cache가 import가 잘 안잡힐 때, import { Cache } from 'cache-manager'; 해당 값으로 넣어주면 된다.
    constructor(private readonly appService: AppService,
                @Inject(CACHE_MANAGER) private cacheManager: Cache) {}

    @Get('/cache')
    async findAll(): Promise<string[]> {
        const result = await this.cacheManager.get('malgogi');

        if(result) {
          return result;
        }

        await this.cacheManager.set('malgogi', this.testCache(), { ttl: 30 });
    }

4. 결론

  • 우선 기본적인 cache manager를 활용해보았다.
  • 편리하긴 하지만 몇가지 제약사항이 눈에 띈다. ( redis에서 지원하는 data structure 전체를 자유롭게 이용하는데, 제약사항이 있다. )
  • 다음 시간에는 좀 더 자세한 사항을 체크해서 해보아야겠다.

출처

728x90
반응형