안녕하세요티비~
제 개념 형상관리를 위해서 오늘부터 벨로그를 쓰기로 했어요 ^~^
처음에는 cache-manager에서 타입을 redis로 잡고 사용을 하고 있었는데,
저는 redis의 hash기능이나 set기능을 쓰고 싶었어요!
그런데 cache-manager는 이런 레디스 자료형을 사용하는 기능을 지원하지 않는것 같더라구요..
(아님말고?)
그래서 그냥 redis 라이브러리를 가져와서 만들기로 결정했어요!
npm install @liaoliaots/nestjs-redis ioredis
yarn add @liaoliaots/nestjs-redis ioredis
pnpm add @liaoliaots/nestjs-redis ioredis
사용하시는 패키지 매니저에 따라서 쓰시는걸로 설치해주세요!
저는 데이터베이스를 임포트할때 콘피그를 따로 빼는걸 좋아하는 편이에요.
그리고 env에서 크레덴셜을 받아올거라서 따로 콘피그 클래스를 만들어주었어요!
import { Injectable } from '@nestjs/common';
import {
RedisOptionsFactory,
RedisModuleOptions,
} from '@liaoliaots/nestjs-redis';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class RedisConfigService implements RedisOptionsFactory {
constructor(private configService: ConfigService) {}
async createRedisOptions(): Promise<RedisModuleOptions> {
return {
config: {
host: this.configService.get<string>('REDIS_HOSTNAME'),
port: this.configService.get<number>('REDIS_PORT'),
password: this.configService.get<string>('REDIS_PASSWORD'),
},
};
}
}
이렇게 하면 .env 파일에서 3가지 크레덴셜만 있으면 레디스에 접속할 수 있어요.
import { Module } from '@nestjs/common';
import { RedisModule } from '@liaoliaots/nestjs-redis';
import { CacheService } from './cache.service';
@Module({
imports: [RedisModule],
providers: [CacheService],
exports: [CacheService],
})
export class CacheModule {}
@Module({
imports: [
ConfigModule.forRoot(),
RedisModule.forRootAsync({
imports: [ConfigModule],
useClass: RedisConfigService,
inject: [ConfigService],
}),
CacheModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
이렇게 AppModule에서 ConfigModule을 RedisConfigService에 주입하게 해서
RedisConfigService 내부에서 ConfigService를 사용하실 수가 있어요~~
useClass로 분리하지 않고 그냥 useFactory를 사용해서 설정하시는 방법도 있는데 저는 중괄호가 길어지는걸 싫어하는 스타일이셔서 그냥 콘피그를 위와같이 따로 분리했어요~~
import { Injectable } from '@nestjs/common';
import { Redis } from 'ioredis';
import { RedisService } from '@liaoliaots/nestjs-redis';
@Injectable()
export class CacheService {
private readonly redisClient: Redis;
constructor(private readonly redisService: RedisService) {
this.redisClient = redisService.getClient();
}
async get(key: string): Promise<string> {
return this.redisClient.get(key);
}
async set(key: string, value: string, expire?: number): Promise<'OK'> {
return this.redisClient.set(key, value, 'EX', expire ?? 10);
}
async del(key: string): Promise<number> {
return this.redisClient.del(key);
}
}
우선 간단하게 get, set, del만 구현을 해보았어요!
hset, mset같은것도 redisClient에다가 쓸 수 있어요!
공식문서에 따르면 저는 constructor에서 di로 인젝션을 받았지만, @InjectRedis 데코레이터를 달아서 그냥 바로 Redis 객체를 받을수도 있다고 해요.
import { CacheService } from './cache.service';
import { Test } from '@nestjs/testing';
import { RedisModule } from '@liaoliaots/nestjs-redis';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisConfigService } from './cache.config';
describe('CacheService', () => {
let cacheService: CacheService;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
imports: [
ConfigModule.forRoot(),
RedisModule.forRootAsync({
imports: [ConfigModule],
useClass: RedisConfigService,
inject: [ConfigService],
}),
],
providers: [CacheService],
}).compile();
cacheService = moduleRef.get<CacheService>(CacheService);
});
describe('set', () => {
it('should be defined', () => {
expect(cacheService.set).toBeDefined();
});
it('should return Ok', async () => {
const result = await cacheService.set('test', 'test', 100);
expect(result).toBe('OK');
});
});
describe('get', () => {
it('should be defined', () => {
expect(cacheService.get).toBeDefined();
});
it('should return test', async () => {
await cacheService.set('test', 'test', 100);
const result = await cacheService.get('test');
expect(result).toBe('test');
});
});
});
저는 참된 개발자가 되기 위하여 유닛 테스트도 간단하게 작성해보았어요~
아무쪼록 잘되는것같으니까 이만 줄이도록 하겠습니다티비~
즐코딩하세요 OwO~
안녕하세요 글 재밌게 잘봤습니다
혹시 설치하신 패키지 버전이 v9 일까요?