[Nest] Redis Cache 적용

오준석·2023년 11월 10일
1

TIL (Today I Learned)

목록 보기
105/105

개요

Nest.js로 구성 되어 있는 프로젝트의 특정 코드를 Redis를 이용해 캐시 기능을 활용해보려는 목적

코드

Nest.js 컨트롤 및 서비스 일부 코드 (재료를 전체 조회(Get)하는 로직을 캐싱해봄)

// ingredient.controller
import {
  UseInterceptors,
} from '@nestjs/common';
import { CacheInterceptor, CacheKey, CacheTTL } from '@nestjs/cache-manager';
import { number } from '@hapi/joi';

  // 재료 전체조회 (캐싱할 API)
  @Get('/')
  async getIngredientAll() {
    return this.ingredientService.getIngredientAll();
  }
// ingredient.service
import {
  Inject,
} from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

@Injectable()
export class IngredientService {
  constructor(
    @Inject(CACHE_MANAGER) private cacheService: Cache,
  ) {}

    //재료 전체 조회 (캐싱할 API)
  async getIngredientAll() {
    const cachedData = await this.cacheService.get('/ingredient')
    return cachedData;
  }

아래와 같은 결과 값을 얻을 수 있었다.

문제

ElastiCache 서비스를 이용하여 ElastiCache 경로 설정 후 빌드 시(npm run start:dev) 오류 발생 (Redis 캐시 활용 목적)

시도

1. ElastiCache 의 설정을 바꿔본다.

Amazon ElastiCache 의 설정을 바꿔보거나 여러 시도를 해봄

  • 기본 엔드포인트 및 리더 엔드포인트 경로로 설정 시 동일한 오류 발생
  • 혹시 몰라 ARN 을 경로로 설정해 보니 TypeError [ERR_INVALID_URL]: Invalid URL 라는 에러 발생

2. github issue 에 올라온 내용을 통한 문제 탐색

참고 : https://github.com/redis/node-redis/issues/1656

  • 해당 내용 중 ioredis 라이브러리를 사용해서 해결했다는 의견이 있었음.
  • node-redis v4.6.1를 사용해서 해보라는 의견이 있었고, 아래 코드를 참조해보라는 의견이 있었다.
RedisClient = createClient({
  url: `redis://${process.env.REDIS_CLIENT_HOST}:${process.env.REDIS_CLIENT_PORT}`,
  username: process.env.REDIS_USERNAME,
  password: process.env.REDIS_PASSWORD,
  socket: {
    connectTimeout: 50000,
  },
});
  • pingInterval 옵션 사용 의견 있었음
// Has anyone here tried using the pingInterval option?

createClient({
  url: "redis://localhost:6379",
  pingInterval: 1000,
})

// I am using node-redis (via redis-om) with Deno+Fresh, and a clean Redis Stack container running in a local Docker. Here's what I did, it seems to have solved the issue for now. Hope this helps someone.

import { Client } from "npm:redis-om"
import { createClient } from "npm:redis"

const nodeClient = createClient({
  url: "redis://localhost:6379",
  pingInterval: 1000,
})
await nodeClient.connect()
const omClient = new Client()
const redis = await omClient.use(nodeClient)

export { redis }

3. Redis 서버를 직접 설치해서 원격 설정을 해볼까? 라는 생각을 함

참고 : https://cloud-oky.tistory.com/395
참고 : https://jindevelopetravel0919.tistory.com/187

  • Ec2 접속 후 vim redis.conf 로 편집기를 열어 127.0.0.1 ::1 이라고 되어 있는 걸 bind 0.0.0.0 ::1 로 수정

  • 서버를 재시작하는 명령어를 사용했는데 실패를 했다고 나옴

  • 진행하다가 Redis 직접 설정 보단 ElastiCache 서비스가 제대로 연결되는 지를 확인해보기로 결정했다. 애초에 계획이 이번 프로젝트는 클라우드 서비스를 이용하여 Redis Cache를 적용하는 게 목표였기에 추후에 기회가 된다면 Redis 서버를 통한 직접 연결을 해보기로 하고 클라우드 서비스를 이용하기로 했다.

해결

주변 동료가 ElastiCache로 적용하는 대신 Redis Labs를 통한 방법을 통하면 간단하게 Redis 이용이 가능하다고 조언해주었고, Redis Labs를 통한 연결을 알려주어 손쉽게(?) 연결할 수 있었다.

import { CacheModule, CacheStore } from '@nestjs/cache-manager';
import { redisStore } from 'cache-manager-redis-store';
import type { RedisClientOptions } from 'redis';

@Module({
  imports: [
    CacheModule.registerAsync<RedisClientOptions>({
      isGlobal: true,
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        store: (await redisStore({
          url: configService.get('REDIS_URL'),
        })) as unknown as CacheStore,
        ttl: 0,
      }),
      inject: [ConfigService],
    }),

url: configService.get('REDIS_URL')에서 URL 경로는 아래와 같은 형태로 redis-labs을 활용하면 손쉽게 연결이 가능하다!

마무리

Redis 캐시를 사용해서 일부 코드에 사용하여 경험해 보았지만, 애초에 계획한 ElastiCache 서비스를 사용하지 않고 redis-lab를 통해 실행한 건 아쉬움이 남는다.

물론 ElastiCache에 비해 redis-lab은 비용면에서 큰 장점을 갖고 있기에 선택 이유도 충분하지만 ElastiCache 서비스도 경험하고 싶단 생각을 하기에 추후에 ElastiCache 서비스 또한 경험해 보고 게시글을 작성하겠다.

도움을 준 김O령님과 장O혁님에게 감사합니다.😘
profile
개발자를 목표로 열심히 하려고 합니다.

0개의 댓글