NestJS 캐시 메모리 사용하기

권태형·2023년 5월 22일
0

NestJS 연습

목록 보기
17/19
post-thumbnail

이번포스팅에서는 NestJS 프로젝트에서 캐시메모리를 사용해보자.

NestJS 공식페이지에서는 caching을 사용하기 쉽도록 잘 설명되어있다.

1. 먼저 캐시 메모리를 이용하기 위한 라이브러리들을 npm을 통해 설치해준다.

$ npm install @nestjs/cache-manager cache-manager

이때 그냥 위와 같이 설치하면 5버전대가 설치됨으로 TTL(Time To Live)이 밀리초 단위가 된다는 것을 미리 알아둬야한다.

여러 포스팅을 보면서 참고해서 캐시 매니저를 사용했었는데 불과1년도 안된 포스팅이었지만 해당 포스팅들은 그냥 초 단위의 TTL을 사용하였다.

따라서 3분의 시간 측 180이라는 TTL을 넣었지만, 필자는 180밀리초가 되어 눈 깜짝할 시간도 없이 데이터가 들어갔다가 삭제되는 일이 일어났었다.

2. 필요한 모듈에 CacheModule.register()를 임포트

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

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

TTL설정하는 방법은 직접 메소드에서 TTL을 생성하는 방법과 위의 주입시킨 register에서 고정하는 방법이 있다.

CacheModule.register({
  ttl: 5000, // 시간(밀리초)
  max: 10, // 캐시에 담길 최대 데이터 개수
  isGlobal: true, // 캐시모듈을 전역설정
});

위의 설정처럼 TTL과 MAX를 설정해 줄 수 있고, 전역설정도 가능하다.
만약 원하는 모듈에서만 사용하고 싶다면, 해당 모듈에서 CacheModule.register()를 임포트 해서 사용하면 된다.

두 개 이상의 모듈에서 사용하기 위해서는 임포트한 캐시모듈은 익스포트하고, 또 다른 모듈에서 임포트하는 번거로운 과정이 이루어 지기 때문에, 여러곳에서 캐시모듈을 사용할 경우 root모듈에서 isGlobal옵션을 주자.

3. 생성자에 @Inject데코레이터를 이용해 클래스 주입

import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
//...//
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

자동임포트를 통해서 가져오면 에러가 발생할 수 있으니 위에 임포트 구문을 꼭 참고하자.

4. cacheManager.메소드를 통해 이용

캐시메모리는 임시 저장소와 같다. 따라서 해당 저장소에 저장하고, 가져오고, 삭제할 수 있는 메소드들을 가지고있다.

1. 저장하기

일반적으로 key와 value 한 쌍씩 캐시 메모리에 저장한다.

await this.cacheManager.set('key', 'value')

내가 저장할 데이터에 대해서만 생존시간(TTL)을 설정하고 싶다면 3번째 인자로 넣어주면 되고, 만약 메모리에 계속 유지하고 싶다면 0을 넣어주면 된다.

await this.cacheManager.set('key', 'value', 180000)//3분간 생존하는 데이터
await this.cacheManager.set('key', 'value', 0)// 생존 만료시간 없음

2. 가져오기

저장했으면 가져와서 확인해 보면 된다. 간단하게 get메소드와 key를 인자로 주면 값을 가져온다.

const a = await this.cacheManager.get('key');
console.log(a) // value

3. 삭제하기

캐시에 저장된 임시 데이터를 이미 사용했음에도 불구하고 데이터가 남아있거나, 같은 key로 새로운 데이터를 넣기전에는 해당 데이터를 지워줄 필요가 있다. 가져오기와 마찬가지고 간단하게 del메소드와 key를 인자로 주면 해당 key를 가진 데이터가 제거된다.

await this.cacheManager.del('key')

cacheManager.del('key')은 해당하는 key에 대한 값을 삭제하므로 하나씩 삭제하게 되는데, 캐시 내의 모든 데이터를 삭제하고싶다면 reset메소드를 사용하면 된다.

await this.cacheManager.reset();

필자는 임시 데이터의 저장공간이라는 생각으로 일회용 휘발성 데이터를 저장하는데 사용하였다. 휴대폰 인증로직에서 한번 사용하게 될 난수와 같은 일회성 데이터를 저장하고 3분이라는 시간내에 인증하도록 TTL을 설정하였다.

//SMS보내기
  async sendSms(sendSmsDto: SendSmsDto) {
    const timestamp = Date.now().toString();

    //헤더의 시그니처 생성
    const signature: string = this.makeSignature(timestamp);

    //인증을 진행할 난수 생성
    const code: string = this.createRandomNum().toString();

    //.....//

    //혹시 이미 존재할 동일 key의 캐시데이터 삭제
    await this.cacheManager.del('BnbPhoneNumberCheckCode');

    //캐시에 인증code 저장 3분간
    await this.cacheManager.set('BnbPhoneNumberCheckCode', code, 180000);
  }

  //SMS인증 코드 확인
  async checkSms(checkSmsDto: CheckSmsDto): Promise<boolean> {
    //캐시에 저장된 인증code를 변수에 담기
    const certificationCode = await this.cacheManager.get(
      'BnbPhoneNumberCheckCode',
    );

    //인증code와 입력된code를 비교해서 처리
    if (certificationCode !== checkSmsDto.checkCode)
      throw new BadRequestException('인증 코드가 일치하지 않습니다.');
    return true;
  }
profile
22년 12월 개발을 시작한 신입 개발자 ‘권태형’입니다. 포스팅 하나하나 내가 다시보기 위해 쓰는 것이지만, 다른 분들에게도 도움이 되었으면 좋겠습니다. 💯컬러폰트가 잘 안보이실 경우 🌙다크모드를 이용해주세요.😀 지적과 참견은 언제나 환영합니다. 많은 댓글 부탁드립니다.

0개의 댓글