프로젝트 (Java)/예약마켓

[프로젝트] 31. 알림 관련 데이터 삭제 기능 추가

hihyuk 2024. 1. 31. 09:50

프로젝트에 알림 관련 데이터 삭제 기능을 추가하는 것은 데이터의 일관성과 무결성을 유지하는 데 중요합니다. 특히, 게시물, 댓글, 좋아요 등의 행위에 대한 알림이 생성된 후 해당 데이터가 삭제되는 경우, 관련 알림 또한 함께 삭제되어야 합니다. 이를 통해 사용자가 존재하지 않는 데이터에 대한 알림을 받는 것을 방지할 수 있습니다.

 

Notification 엔티티 수정

Notification 엔티티에 postId 필드를 추가하여, 게시물에 대한 알림과 관련된 게시물의 ID를 저장할 수 있게 합니다. 이를 통해 특정 게시물에 대한 모든 알림을 쉽게 조회하고 삭제할 수 있습니다.

    @Column(name = "post_id")
    private Long postId;

 

NotificationRepository 수정

NotificationRepository에는 특정 게시물 또는 행위(typeId)에 대한 모든 알림을 삭제하는 메서드를 추가합니다. 이는 @Modifying @Query 어노테이션을 사용하여 구현할 수 있습니다.

public interface NotificationRepository extends JpaRepository<Notification, Long> {
    @Modifying
    @Query(value = "INSERT INTO notifications(from_user_id, to_user_id, type, post_id, type_id, created_at) VALUES(?1, ?2, ?3, ?4, ?5, now())", nativeQuery = true)
    int mSave(Long fromUserId, Long toUserId, String type, Long postId, Long typeId);

    Optional<Notification> deleteAllByPostId(Long postId);
    Optional<Notification> deleteAllByTypeId(Long typeId);
}

 

FollowService와 PostService에서 알림 삭제 로직 추가

FollowService에서는 사용자가 어떤 사용자를 팔로우 취소할 때, 해당 팔로우 관련 알림을 삭제합니다. PostService에서는 사용자가 좋아요를 취소하거나 댓글을 삭제할 때, 관련 알림을 삭제합니다. 이를 통해 관련 데이터가 삭제될 때 알림도 함께 삭제되어 데이터의 일관성을 유지합니다.

 

FollowService

        Optional<Follow> existingFollow = followRepository.findByFollowerAndFollowing(user, following);
        if (existingFollow.isPresent()) {
            // 이미 팔로우한 경우
            Long followId = existingFollow.get().getId();
            followRepository.delete(existingFollow.get());
            notificationRepository.deleteAllByTypeId(followId);
        } else { // 아닌 경우 팔로우
            Follow follow = new Follow();
            follow.setFollower(user);
            follow.setFollowing(following);
            followRepository.save(follow);
            notificationRepository.mSave(userId, followingId, NotiType.FOLLOW.name(), 0L, follow.getId());
        }

PostService

            Map<Long, Like> likes = post.getLikes()
                    .stream()
                    .collect(Collectors.toMap(Like::getUserId, Function.identity()));
            Like like = likes.get(userId);
            post.removeLike(like);
            notificationRepository.deleteAllByTypeId(like.getId());
        }
        else { // 좋아요
            Like like = Like.builder().userId(userId).build();
            post.addLike(like);
            likeRepository.save(like);
            notificationRepository.mSave(userId, post.getUser().getId(), NotiType.LIKE.name(), postId, like.getId());
        }
        
        // 생략
        
        Comment newComment = commentDto.toEntity(user);
        post.addComment(newComment);
        commentRepository.save(newComment);
        notificationRepository.mSave(userId, post.getUser().getId(), NotiType.COMMENT.name(), postId, newComment.getId());
        
        // 생략
        
        post.removeComment(comments.get(commentId), userId);
        notificationRepository.deleteAllByTypeId(commentId);

 

결론

이와 같은 구현을 통해, 알림과 관련된 데이터의 삭제 시 그와 관련된 모든 알림 또한 함께 삭제되도록 하여, 사용자가 유효하지 않은 데이터에 대한 알림을 받지 않도록 보장합니다. 이는 애플리케이션의 사용자 경험을 향상시키고, 데이터의 무결성을 유지하는 데 기여합니다.