Issues encountered
- Liked Posts GET API에서
include
를 사용해서 foreign key 활용하기
- Likes POST API에서 transaction 구현하기
What I tried
- 처음에는 이중 map을 돌려서 Like 모델에서 Like를 누른 postId를 가져오고 그 postId를 가지고 Post 모델에서 원하는 attributes를 가져오는 방식을 사용했지만,
include
를 통해 이를 한 번에 해결할 수 있는 걸 알게되었고, 다음과 같이 구현하였다.
findLikedPosts = async (userId) => {
const likedPosts = await Likes.findAll({
include: [
{
model: Posts,
attributes: [
"postId",
"UserId",
"nickname",
"title",
"createdAt",
"updatedAt",
"like",
],
},
],
where: { UserId: userId },
attributes: [],
order: [[Posts, "like", "DESC"]],
});
- 데이터베이스에 두 번 접근을 하여 중간에 오류가 날 시 rollback이 필요한 부분이 like POST API였다. 우리는 해당 API에서 유저가 좋아요를 누르면 1) userId, postId가 Like 테이블로 추가가 되고, 2) Posts 테이블의 like attribute의 값을 하나 올려주는 방식으로 구현을 하였다 (좋아요 취소의 경우 반대로). 이때 1번째 동작만 되고 오류가 났을 경우를 대비하여 controller에서 transaction을 사용해주었다.
const t = await sequelize.transaction({
isolationLevel: Transaction.ISOLATION_LEVELS.READ_COMMITTED,
});
try {
const existingLike = await this.postService.findLike(
_postId,
userId
);
if (!existingLike) {
await this.postService.createLike(userId, _postId, {
transaction: t,
});
await this.postService.incrementLike(_postId, {
transaction: t,
});
await t.commit();
res.status(200).json({
message: "게시글의 좋아요를 등록하였습니다",
});
} else {
await this.postService.deleteLike(userId, _postId, {
transaction: t,
});
await this.postService.decrementLike(_postId, {
transaction: t,
});
await t.commit();
res.status(200).json({
message: "게시글의 좋아요를 취소하였습니다.",
});
}
} catch (error) {
await t.rollback();
throw new Error(
error.message || "400/게시글 좋아요에 실패하였습니다."
);
}
What I newly learned
- 3-layered architecture를 직접 적용시켜보았다.
- Redis
What to learn next
- Redis로 refresh token 저장하기
- refresh token 만료 에러 해결하기