diff --git a/src/main/java/greeny/backend/domain/community/controller/PostLikeController.java b/src/main/java/greeny/backend/domain/community/controller/PostLikeController.java index 39774e8..a7bc78a 100644 --- a/src/main/java/greeny/backend/domain/community/controller/PostLikeController.java +++ b/src/main/java/greeny/backend/domain/community/controller/PostLikeController.java @@ -32,7 +32,7 @@ public class PostLikeController { @ResponseStatus(OK) @PostMapping() public Response togglePostLike(Long postId) { - postLikeService.togglePostLike(postId, memberService.getCurrentMember()); + postLikeService.like(postId, memberService.getCurrentMember()); return success(SUCCESS_TO_TOGGLE_POST_LIKE); } diff --git a/src/main/java/greeny/backend/domain/community/repository/PostLikeRepository.java b/src/main/java/greeny/backend/domain/community/repository/PostLikeRepository.java index 486e90c..b876e85 100644 --- a/src/main/java/greeny/backend/domain/community/repository/PostLikeRepository.java +++ b/src/main/java/greeny/backend/domain/community/repository/PostLikeRepository.java @@ -8,6 +8,5 @@ import java.util.Optional; public interface PostLikeRepository extends JpaRepository { - @Lock(LockModeType.PESSIMISTIC_WRITE) // 동시성 문제 방지를 위해 Pessimistic lock 사용 Optional findByPostIdAndLikerId(Long postId, Long likerId); } diff --git a/src/main/java/greeny/backend/domain/community/service/PostLikeService.java b/src/main/java/greeny/backend/domain/community/service/PostLikeService.java index 6c1add7..d49eef0 100644 --- a/src/main/java/greeny/backend/domain/community/service/PostLikeService.java +++ b/src/main/java/greeny/backend/domain/community/service/PostLikeService.java @@ -8,37 +8,59 @@ import greeny.backend.exception.situation.PostNotFoundException; import greeny.backend.exception.situation.SelfLikeNotAllowedException; import lombok.RequiredArgsConstructor; +import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - import java.util.Optional; @Service @RequiredArgsConstructor public class PostLikeService { - private final PostLikeRepository postLikeRepository; - private final PostRepository postRepository; - // 좋아요 or 취소 - @Transactional - public void togglePostLike(Long postId, Member liker) { - Optional postLike = postLikeRepository.findByPostIdAndLikerId(postId, liker.getId()); - // 이미 좋아요 눌렀는지 확인 - if(postLike.isEmpty()) likePost(postId, liker); // 안 눌렀다면 좋아요 수행 - else postLikeRepository.delete(postLike.get()); // 이미 눌렀다면 취소 수행 - + public void like(Long postId, Member liker) { + boolean retry; + do { + try { + retry = false; + Optional foundPostLike = findPostLike(postId, liker.getId()); + toggle(postId, liker, foundPostLike); + } + catch (OptimisticLockingFailureException e) { + retry = true; + } + } while (retry); } - // 게시글 좋아요 - public void likePost(Long postId, Member liker){ - Post post = postRepository.findByIdWithWriter(postId).orElseThrow(PostNotFoundException::new); - if(post.getWriter().getId().equals(liker.getId())) throw new SelfLikeNotAllowedException(); // 자기의 게시글에는 좋아요를 누를 수 없음 + public void create(Long postId, Member liker) { + Post post = getPost(postId); + if (post.getWriter().getId().equals(liker.getId())) + throw new SelfLikeNotAllowedException(); postLikeRepository.save(PostLike.builder() .post(post) .liker(liker) .build()); } + + public Post getPost(Long postId) { + return postRepository.findByIdWithWriter(postId).orElseThrow(PostNotFoundException::new); + } + + public Optional findPostLike(Long postId, Long likerId) { + return postLikeRepository.findByPostIdAndLikerId(postId, likerId); + } + + private void delete(PostLike postLike) { + postLikeRepository.delete(postLike); + } + + private void toggle(Long postId, Member liker, Optional postLike) { + if (postLike.isEmpty()) { + create(postId, liker); + return; + } + delete(postLike.get()); + } } diff --git a/src/main/java/greeny/backend/domain/community/service/PostService.java b/src/main/java/greeny/backend/domain/community/service/PostService.java index 45bc31e..09a6427 100644 --- a/src/main/java/greeny/backend/domain/community/service/PostService.java +++ b/src/main/java/greeny/backend/domain/community/service/PostService.java @@ -124,7 +124,7 @@ public void editPostInfo(Long postId, WritePostRequestDto editPostInfoRequestDto } @Transactional - protected void uploadPostFileList(List multipartFiles, Post post) { + public void uploadPostFileList(List multipartFiles, Post post) { // s3에 파일을 업로드 한 뒤 예외가 발생하면 db는 롤백이 되지만, // 이미 s3에 저장된 이미지는 삭제되지 않는 문제가 있음.