TIL_2023.07.06

이얏호·2023년 7월 6일
0
post-custom-banner

어제 고려했던 방식으로 코드를 짜봤다.
우선 Posts 모델에 likeCount 칼럼을 추가하고
새로 Likes 모델을 만들어 userId와 postId를 유지시켰다.

그러다가 문제가 발생했는데,....

const express = require('express');
const router = express.Router();
const { Posts, Users, Likes, sequelize } = require('../models');
const { Transaction } = require('sequelize');
const authMiddleware = require('../middlewares/auth-middleware.js');

router.patch('/posts/:postId/like', authMiddleware, async (req, res) => {
  const { userId } = res.locals.user;
  const { postId } = req.params;

  const post = await Posts.findOne({
    attributes: ['postId', 'likeCount'],
    include: [
      {
        model: Users,
        attributes: ['userId'],
      },
    ],
    where: { postId },
  });
  if (!post) {
    res.status(404).json({
      errorMessage: '존재하지 않는 게시글입니다.',
    });
    return;
  }

  const likes = await Likes.findOne({
    where: { [Op.and]: [{ PostId: postId }, { UserId: userId }] },
  });

  const t = await sequelize.transaction({
    isolationLeverl: Transaction.ISOLATION_LEVELS.READ_COMMITTED,
  });
  try {
    if (!likes) {
      await Likes.create(
        {
          UserId: userId,
          PostId: postId,
        },
        { transaction: t }
      );
      await Posts.update(
        { likeCount: post.likeCount + 1 },
        { where: { postId } },
        { transaction: t }
      );
    } else {
      await Likes.destroy({ where: { postId } }, { transaction: t });
      await post.update({ likeCount: post.likeCount - 1 }, { transaction: t });
    }
  } catch (error) {
    await t.rollback();
    return res
      .status(400)
      .json({ errorMessage: '좋아요 수정에 실패했습니다.' });
  }

  await t.commit();
  return res.status(200).json({ message: '좋아요 변경이 완료됐습니다.' });
});

문제가 되는 부분은

...

if (!likes) {
      await Likes.create(
        {
          UserId: userId,
          PostId: postId,
        },
        { transaction: t }
      );
      await Posts.update(
        { likeCount: post.likeCount + 1 },
        { where: { postId } },
        { transaction: t }
      );
    }
    
    ...

해당 부분의 await Likes.create 였는데
정말.. 이상하게도 다음과 같이 create와 update의 순서를 바꾸어 주었더니 오류가 해결되었다.

      await Posts.update(
        { likeCount: post.likeCount + 1 },
        { where: { postId } },
        { transaction: t }
      );
      await Likes.create(
        {
          UserId: userId,
          PostId: postId,
        },
        { transaction: t }
      );

아무리 생각해보아도 순서에 의해서 문제가 생긴다는게 와닿지 않았다.
혹시나 교착상태가 발생하나 고민도 해보았으나,
postId는 params 값으로, userId값은 authMiddleware에서 참조해오고 각기 다른 테이블에서 실행되기 때문에 교착상태가 생길 것 같지는 않았는데 순서를 바꿔주는 것으로 문제가 해결됐다...

다른 방식으로
Posts 모델자체를 참조해서 where로 걸러내어 update를 하는 것이 아니라
위에서 받아오고 있는

const post = await Posts.findOne({
    attributes: ['postId', 'likeCount'],
    include: [
      {
        model: Users,
        attributes: ['userId'],
      },
    ],
    where: { postId },
  });

이 post값을 불러와 다음과 같이 작성하였다.

		await Likes.create(
        {
          UserId: userId,
          PostId: postId,
        },
        { transaction: t }
      );
      await post.update({ likeCount: post.likeCount + 1 }, { transaction: t });

post자체로 update를 사용하고 where을 제거해주자 create와 update의 위치와 관계없이 정상 작동 하였다.

profile
열심히 신나게 화이팅!
post-custom-banner

0개의 댓글