팀 작업 중이었는데,
우선 제한 사항부터 기술해보자면,
팀원 분이 버전 호환 이슈로 redis를 3.1.2버전을 설치하였다.
그 상태에서 작업을 진행하던 중,
배열 상태로 통째로 redis에 set을 할 일이 생겼다.
for문을 돌리면 너무 비효율적일 것 같아서 방법을 찾아봤는데
mset()이라는 메서드가 존재했다.
사용을 해보려고 했으나, 현재 사용된 캐시매니저와 레디스 구버전 등등의 이유로 사용이 불가했다...
그래서 레디스 자체 메서드 중 3.2.1버전에서 사용가능한 방법을 찾다보니
hmset()이 존재했다.
hmset('해시이름',['필드','밸류','필드2','밸류2])의 형식으로 사용이 가능하며,
최종적으로는 해시 이름으로 묶인 채 내부에 필드명 / 벨류 형식으로 저장이 된다.
구현하고자 했던 기능이 누적 판매량 관련 저장 부분이었어서 사용하는데에 지장이 없었는데,
문제는 불러올 때 있었다.
hmget / hget / mget / get ... 등등의 없어지거나 새로 생긴 메서드들을 사용해봤으나 제대로 작동하지 않았고,
hgetall()이라는 메서드가 작동은 했는데 도무지 반환 값이 받아지지 않았다.
const rank = await redisClient.hgetall('rank');
다음과 같은 형식으로 rank에 할당해주면 rank는 true값을 반환한다.
내부 값을 받는 방법으로
let data;
console.log(1)
await redisClient.hgetall('rank', function((err, obj) => {
data = obj
console.log(obj)
}));
console.log(data)
위와 같이 구성을 하고 돌려보면,
내부에 있는 console.log(obj)는 정상적으로 redis에 저장된 값이 로그로 남지만
console.log(data)에서는 obj값이 찍히지 않는다.
처음부터 해본건 아니지만 위와 같이 구성하고 로그를 살펴보았을 때,
1 -> obj > data 순서로 찍히는게 아니라
1 -> data -> obj의 순서로 찍히는 것을 확인했다.
해결 방법으로 오버라이딩을 사용했다.
redisService를 만들어서 내부에 hgetall을 만들어주기로 했다.
import { BadRequestException, Injectable } from '@nestjs/common';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const redis = require('redis');
const client = redis.createClient();
@Injectable()
export class RedisService {
async hgetall(key: string): Promise<{ [key: string]: string }> {
return new Promise<{ [key: string]: string }>((resolve, reject) => {
client.hgetall(key, (err, reply) => {
if (err) {
console.error(err);
throw new BadRequestException();
}
resolve(reply);
});
});
}
}
이렇게 hgetall을 promise로 선언해주고, 실제 client.hgetall의 값을 resolve에 담아주어서 값을 반환받는데에 성공했다.
아래는 예시
const rank = await this.redisService.hgetall('rank');
이렇게 하면 rank 변수에 redis의 값이 정상적으로 할당된다.
구버전 redis로 고생받는 사람이 없었으면 좋겠다...