[ 2024.11.22 TIL ] redis로 세션 데이터 관리

박지영·약 5시간 전
0

Today I Learned

목록 보기
84/84

레디스 연결

모노레포에서 redis client 사용하기

하위 서비스들에서 각각 레디스 클라이언트를 사용하기 위해서 어떤 방법이 있을까 고민해보았다.

서비스 별로 구현하기

  1. 하위 서비스들이 상속받을 RedisClient 클래스를 구현.

    • host, port 등 연결에 관련된 생성자만 있는 클래스

      import Redis from 'ioredis';
      
      class RedisClient {
        constructor(config) {
          this.client = new Redis({
            host: config.host || 'localhost',
            port: config.port || 6379,
            password: config.password,
          });
          this.client.on('error', (err) => {
            console.error('Redis error: ', err);
          });
          this.client.on('connect', () => {
            console.log('Redis connect');
          });
        }
        
        getClient() {
          return this.client;
        }
        
        async quit() {
          await this.client.quit();
        }
      }
  2. 유틸 함수 등을 각 서비스의 RedisClient에서 메소드로 구현

    • e.g ) 로비 서버 -> LobbyRedisClient extends RedisClient

      export class LobbyRedisClient extends BaseRedisClient {
        constructor(config) {
          super(config);
          this.prefix = 'lobby';
        }
      
        async addUserToLobby(lobbyId, userId) {
          const key = `${this.prefix}:${lobbyId}:users`;
          await this.client.sadd(key, userId);
        }
      }
  3. 클라이언트 인스턴스 생성 및 사용

      import { LobbyRedisClient, UserRedisClient } from '@repo/common/utils/redis/clients';
    
     const redisConfig = {
       host: process.env.REDIS_HOST,
       port: process.env.REDIS_PORT,
       password: process.env.REDIS_PASSWORD
     };
    
     const server = new LobbyServer(SERVER_NAME, SERVER_PORT);
     server.lobbyRedis = new LobbyRedisClient(redisConfig);
     server.userRedis = new UserRedisClient(redisConfig);

최상위에서 구현하고 패키지로 내보내기

  1. 하위 서비스들이 상속받을 RedisClient 클래스를 구현.

    import Redis from 'ioredis';
    
     class RedisClient {
       constructor(config) {
         this.client = new Redis({
           host: config.host || 'localhost',
           port: config.port || 6379,
           password: config.password,
         });
         this.client.on('error', (err) => {
           console.error('Redis error: ', err);
         });
         this.client.on('connect', () => {
           console.log('Redis connect');
         });
       }
       
       getClient() {
         return this.client;
       }
       
       async quit() {
         await this.client.quit();
       }
     }
  2. 유틸 함수들을 가지고 있는 RedisUtil 클래스 구현

    class RedisUtil {
      constructor(redisClient) {
        this.client = redisClient;
        this.prefix = {
          USER: 'user',
          LOBBY_USER: 'lobbyUser',
          LOBBY_ROOM: 'lobbyRoom',
          ROOM: 'room',
        };
      }
    
      async createUserToSession(userData) {
        const key = `${this.prefix.USER}:${userData.userId}`;
        await this.client.hset(key, {
          userId: userData.userId,
          nickname: userData.nickname,
          location: userData.location,
        });
        await this.client.expire(key, 1800);
      }
    
      async deleteUserToSession(userId) {
        const key = `${this.prefix.USER}:${userId}`;
        await this.client.del(key);
      }
        // 여러 유틸 함수 .....
    }
  3. 하위 서비스에서 사용

    import { RedisClient, RedisUtil } from '@repo/common/classes';
     const redisClient = new RedisClient({
        host: process.env.REDIS_HOST,
        port: process.env.REDIS_PORT,
        password: process.env.REDIS_PASSWORD
     }).getClient();
    
     const redis = new RedisUtil(redisClient);
    
     // 사용례
     await redis.createRoom()

선택한 방법 - 최상위 구현

현재로서는 Redis 관련 부분은 한 사람이 맡는게 최선이고 시간을 절약할 수 있을 것 같아서

혼자 여러 유틸 함수를 미리 구현해놓고 필요한 것만 가져다 사용하는 방법으로 채택했다.

profile
신입 개발자

0개의 댓글