TIL/React
React) 백엔드와 연동하여 좋아요 기능 구현하기 <TIL_2022_07_31>
Dev_to_freedom
2022. 7. 31. 23:58
위 그림과 같이 각 게시글마다 좋아요를 누를 수 있게 하는 기능을 구현하고자 한다.
Likes 테이블 생성, 관계 설정
한 명의 유저가 여러 개의 게시글에 좋아요를 누를 수 있고, 한 개의 게시글에도 마찬가지로 여러명의 좋아요가 기록될 수 있으므로,
user와 questions 테이블은 서로 N : M(다 대 다) 관계를 갖는다.
이들을 이어줄 인자값으로 likes 테이블을 생성한다.
// models/likes.js
const Sequelize = require("sequelize");
module.exports = function (sequelize, DataTypes) {
return sequelize.define(
"likes",
{
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
},
{
sequelize,
tableName: "likes",
charset: "utf8mb4",
collate: "utf8mb4_general_ci",
timestamps: false,
}
);
};
// models/init-models.js
questions.belongsToMany(user, {
as: "likers",
through: likes,
foreignKey: "questionId",
});
user.belongsToMany(questions, {
as: "likedQuestions",
through: likes,
foreignKey: "userId",
});
위와 같이 models 폴더에 likes.js를 추가하고, id값만 정의해준다.
그리고 테이블 간 관계를 정의하는 init-models.js에서 questionId, userId를 각각 foreignKey로 하여 likes 테이블로 questions, user두 테이블을 이어주는 N:M 관계를 선언한다.
위와 같이 likes 테이블이 생성되었다.
(이후 이 likes 테이블을 이용해 '해당 게시물에 좋아요 누른 사람들의 정보 조회', '해당 유저가 좋아요 누른 게시글들의 정보 조회' 등의 기능을 구현할 수 있을 것이다.)
이제 좋아요 기능을 구현해야 하는데, 유저가 좋아요를 중복해서 누르지 못하도록 하는 기능을 구현하는 데에 위의 likes 테이블이 쓰인다.
// questions.ctrl.js
upvoteQuestion: async (req, res) => {
const questionId = req.params.questionId;
const question = await models.questions.findOne({
where: { id: questionId },
});
// 유저id를 클라이언트에서 req.body에 받아온다
const userId = req.body.userId;
// likes 테이블에서 유저의 좋아요 중복 여부를 체크한다
const likes = await models.likes.findOne({
where: {
questionId: questionId,
userId: userId,
},
});
// 좋아요 중복 여부에 따라 true or false를 response로 보낸다
if (!likes) {
await question.update({
upvote: question.upvote + 1,
});
await models.likes.create({
questionId: questionId,
userId: userId,
});
res.send(true);
} else {
res.send(false);
}
},
이후 위처럼 서버에서 보낸 response 값(true or false)을 이용해 클라이언트에서 로직을 구현한다.
// UserDetail.jsx
const onClickLike = async (questionId) => {
if (!isLogged) {
alertAuth();
} else {
await axios
.patch(`${BASE_URL}/questions/upvote/${questionId}`, {
userId: loginData.id,
})
// api에서 받은 값을 이용하여 로직 구현
.then((res) => {
if (!res.data) {
alert("이미 추천하셨습니다.");
} else {
window.location.reload();
}
});
}
};
느낀점
- patch 요청에 대한 response 값을 클라이언트에서 받아 와서 활용하는 것은 처음 구현해본다. patch나 post에서도 클라이언트로 response를 보내서 활용할 수 있다는걸 명심하자.