배꼽파지 않도록 잘 개발해요

[NestJS] 객체를 Redis에 저장할 때 발생한 TypeScript 오류 해결 본문

BackEnd/Express / NestJS

[NestJS] 객체를 Redis에 저장할 때 발생한 TypeScript 오류 해결

꼽파 2024. 8. 26. 09:02

redisClient에 세션 ID를 넣어주는 코드를 작성하던 중 오류가 발생하였다.

NestJS는 기본적으로 TypeScript로 만들어졌기 때문에 타입스크립트를 사용한다.

 

타입스크립트는 런타임이 아닌 컴파일타입 오류를 발생시킨다.

그래서 코드 작성할 때 시간이 꽤 걸리지만 서버 실행 중 오류가 발생하는 것보다는 백배 낫다.

Object literal may only specify known properties, and 'sessionId' does not exist in type 'Buffer'.ts(2353)
(property) sessionId: Promise<string>

 

현상

  • 객체를 set 메소드에 직접 전달할 때 타입 에러가 발생하고 있다.

문제

  • Object literal이 특정 타입에 맞춰서 작성되어야 하는데, Buffer 타입에 sessionId라는 속성이 정의되어 있지 않아서 오류가 나고 있다.
  • 나의 의도는 {sessionId: sessionId, userId: user.userId} 라는 객체를 value로 넣어주는 것이었다.

원인

  • Object literal이 buffer 타입으로 잘못 인식되고 있기 때문에 발생한다.
  • Redis는 string이나 buffer타입만 인식하는데, 내가 쓴 코드에서 sessionId는 promise<string>이기 때문에 이게 string이 아닌 buffer로 인식되고 있다.

해결

  • 전달하고자 하는 객체 리터럴을 string으로 명시적으로 바꿔준다.
  • redisClient.hmset 메서드를 사용하여 redis hash 자료구조로 저장한다.

1.  객체 리터럴을 JSON string으로 변환한다.

타입오류가 나지 않는다.

 

const sessionData = await this.redisClient.get(`sessionId:${sessionId}`);
const parsedData = JSON.parse(sessionData);

하지만 이렇게 저장된 JSON 데이터를 불러올 때, JavaScript 객체로 변환해주어야 한다.

왜냐하면 변환된 JSON은 문자열 타입이므로 이 sessionId와 userId라는 key에 접근을 할 수 없다. 그냥 문자 그대로로 인식이 된다.

 

다음 예시를 보면 알 수 있다.

const obj = { sessionId: '1234abc', userId: '0001' };
const jsonString = JSON.stringify(obj);
const parsedjsonString = JSON.parse(jsonString);

console.log(jsonString);  // {"sessionId":"1234abc","userId":"0001"}

console.log(typeof jsonString);  // string
console.log(typeof parsedjsonString);  // object

console.log(jsonString.sessionId);  // undefined
console.log(parsedjsonString.sessionId);  // 1234abc

 

  • JSON.stringify(obj): JavaScript 개체를 JSON 문자열로 변한다.
  • JSON.parse(jsonString): JSON 문자열을 다시 JavaScript 개체로 변환한다.
  • 속성 액세스: JSON.parse를 통해 자바스크립트 개체로 변환해야 해당 문자열이 Object로 인식되어서 속성에 접근이 가능하다.

 

객체 리터럴을 JSON string으로 변환

  • 방법 : 자바스크립트 객체 타입을 보존하기 위해 JSON.stringify와 JSON.parse를 사용한다.
  • 장점 : 자바스크립트 객체 문법을 그대로 사용할 수 있다. (.sessionId로 속성 접근 가능)
  • 단점 : 직렬화 때문에 성능 저하 우려가 있고, JSON.parse를 해줘야하는 것이 귀찮다.

2. redisClient.hmset 메서드로 해시로 저장

hmset은 자바스크립트의 map과 유사한 Redis 해시로 데이터를 저장하는 것이다.

 

 

아래 블로그에 레디스 Hash 자료구조 문법이 잘 정리되어 있다.

 

https://velog.io/@zhyun/Redis-HSET-HGET-HGETALL

 

Redis : HASH 자료구조 :: HSET , HGET , HGETALL , HEXISTS , HDEL , HINCRBY , HINCRBYFLOAT , HSTRLEN , HKEYS , HVALS

 

velog.io

 

단일 value값을 불러올 때는 hget을 쓰면 된다.

자바스크립트 자료구조 Map 문법과 같다.

 

 redisClient.hmset 메서드로 해시로 저장

  • 방법 : redisClient.hmset 메서드로 해시로 저장한다.
  • 장점 : redis 해시 구조를 사용하면 JSON으로 변환하여 저장하고, 다시 JS로 바꿔주는 것보다 액세스 성능이 좋다.
  • 단점 : redis가 지정한 해시 문법을 사용해야 한다.

 

자바스크립트 객체 문법이 더 편하지만, 성능을 위해서 redis 해시를 사용하기로 했다.

 

728x90