express 조회수 중복 방지

9277 단어 expressnode.jsexpress

1. 방법

처음엔 조회수 중복 방지 기능을 쿠키를 사용해 구현 했다.
쿠키를 이용한 조회수 방지의 단점은 다음과 같았다.

  • 쿠키의 최대 개수 문제 👉 쿠키 유효시간을 1분으로 하여 해결하려 함
  • 클라이언트의 쿠키 삭제 및 조작 문제

기획은 조회수 중복 방지였는데 만들고 보니 반쪽 기능이었다.
어정쩡한 기능은 다른 기능에 까지 영향을 끼칠 것이니..

그래서 DB를 이용해 구현하는 것으로 수정했다.


같은 일 두번해버리기 !

2. 구분할 값

로그인한 유저

  • 게시글 아이디
  • 유저 아이디

로그인 하지 않은 유저

  • 게시글 아이디
  • 유저 아이피
  • 사용자 에이전트

요로케 해놓으면 로그인 여부, user agent로 추후에 데이터 분석에도 유용할 듯하다.

3. 코드

컨트롤러

const getPostDetail = async (req, res, next) => {
  try {
    const { user } = req.session;
    const { id } = req.params;
    const userIp = req.ip;
    const userAgent = req.header("User-Agent");
    const post = await postService.getPostDetail(id, userIp, userAgent, user);
    return res.status(200).json(post);
  } catch (err) {
    next(err);
  }
};
  • user : 현재 세션을 사용 중이기에 로그인한 유저의 정보는 세션에 있다.
  • id : 게시글 id
  • userIp : 유저 아이피
  • userAgent : 사용자 에이전트

서비스

const getPostDetail = async (postId, userIp, userAgent, user) => {
  // 게시글 id로 게시글 찾아오기
  let foundPost = await postModel.findById(postId);
  if (!foundPost) throw new CustomError("", 404);

  // 세션 user id와 게시글 id 비교 -> 내 게시글인지 확인
  if (user?.id === foundPost.uid) foundPost.isMyPost = true;
      
  let hasViewed;
  if (user) {
    // 로그인한 유저 -> 유저 id로 조회수 중복 확인
    hasViewed = await postModel.findViewedLoginUser(postId, user.id);
  } else {
    // 로그인 안한 유저 -> userIp와 userAgent값으로 조회수 중복 확인
    hasViewed = await postModel.findViewedUser(postId, userIp, userAgent);
  }

  // 이미 본 게시글이라면 게시글 리턴
  if (hasViewed) return foundPost;

  // 조회수 중복 방지 유저 정보 저장
  await postModel.createViewedUser(
    postId,
    userIp,
    userAgent,
    user ? user.id : 0
  );

  //조회수 1 증가,
  foundPost = await postModel.increaseViewCount(postId);

  return foundPost;
};

모델 쪽 코드는 각자 테이블에 맞게 쿼리를 짜보도록 하자

4. 생각

  • 추후에 레디스도 적용할 수 있는지
  • 2022.03.29
    • 기능적으로 구현하는 것은 좋지만 실제 서비스(사이트)는 보여주기 위해, 어필하기 위해 만드는 것 이라는 피드백을 받음
    • 기획할 당시 생각했던 고민이라 공감함.
    • 기술이 아닌 사용자 측면에서도 생각해보기
    • 하지만 인기글 기능에 영향이 있으니 냅두기로 결정

좋은 웹페이지 즐겨찾기