본문 바로가기
TIL

redis cloud 이용해 조회수 기능 구현하기

by 해룸 2024. 4. 30.

작품과 컬렉션을 조회하면 조회수가 올라가는 기능을 구현하려 한다.

내가 생각했을때 필요한 로직은 다음과 같다.

1. 로그인 사용자와 비로그인 사용자 둘다 조회수에 영향을 준다.

2. 여러번 조회했을때는 한시간에 한번만 조회수에 영향을 준다.

 

해당기능을 구현하기 위해서는 여러가지 방법이 있다.

1. 쿠키를 이용하는 방법. 

2. 세션을 이용하는 방법

3. 레디스 서버를 이용하는 방법. 

 

이 중에서 내가 고려한것은 쿠키 또는 레디스를 이용하는 방법인데,

쿠키를 이용하려면 사용자가 작품을 조회하면 쿠키에 작품 아이디를 넣어 돌려준다.작품 조회 할때마다 사용자가 갖고있는 쿠키에 작품아이디가 있는지 확인해서 있으면 중복조회로 간주, 없으면 조회수 1 추가. 이런식으로 로직을 구현하면 된다.

그러나 쿠키에 담을 수 있는 데이터에는 한계가 있다. 약 2000개 정도의 아이디를 담으면 더 이상 조회한 작품을 추가로 쿠키 페이로드에 담을 수 없다. 그리고 매번 쿠키아이디가 존재하는지 확인하는것도 db에 부담을 준다고 생각했다.

그래서 최종적으로는 레디스를 사용해보려고 한다.

 

레디스 저장방식 중 hash는 필드-값 페어들의 컬렉션이다. 하나의 레디스 키에 대해 다양한 필드를 지닌 객체를 하나 관리하는 구조라고 생각하면 이해하기 쉽다.

 

HSET : 해쉬의 특정 필드에 특정 값을 할당합니다. 이미 값이 존재하면 덮어씁니다.

HGET : 특정 필드의 값을 반환합니다.

HMGET : 특정 필드들의 값들을 반환합니다.

HINCRBY 특정 필드의 숫자 값을 증가 혹은 감소시킵니다.

//webContent.service.ts
async getOneWebContent(user, id: number) {
    const content = await this.webContentRepository.findOne({
      where: { id },
    });

    if (!content) {
      throw new NotFoundException('해당 작품 페이지가 존재하지 않습니다!');
    }

    let userId = user.id;

    if (!user) {
      userId = user.ip;
    }

    console.log('false', userId);

    const key = `user:${userId}:postViews`;

    const existingViews = await this.redisService.isExistingViews(key, id);

    if (existingViews) {
      return content;
    } else {
      await this.redisService.firstViews(key, id);

      await this.webContentRepository.update(content.id, {
        viewCount: content.viewCount + 1,
      });

      return content;
    }
  }

먼저 content를 찾고, 존재할 시 redisService에서 key, contentId 값으로 hget을 해온다.

만약 hget이 존재하면 이미 1시간 안에 조회한 적이 있는 컨텐츠이고, 없다면 조회한적이 없는 컨텐츠다.

그래서 hset을 통해 key, contentId값을 저장하고 해당 컨텐츠의 viewCount를 1을 더한다.