SpringBoot

[instagramProject] 인스타 팔로우 / 좋아요 기능 구현

유쾌한고등어 2023. 3. 5. 18:00

● 팔로우 기능 구현

1. FollowController

- 팔로우 토글 기능 구현

- 클라이언트 요청에 따라 팔로우,언팔로우 개별 api 구현

// FollowController.java
@RequestMapping("/app")
@RestController
public class FollowController {


private final FollowService followService;
private final UserService userService;

private final JwtService jwtService;

@Autowired
public FollowController(FollowService followService, UserService userService,
JwtService jwtService) {
    this.followService = followService;
    this.userService = userService;
    this.jwtService = jwtService;
}

@PostMapping("/follow/postfollow/{toUserId}")
public BaseResponse<?> PostFollow(@PathVariable("toUserId") long toUserId)
throws BaseException{
    try{

        if (!userService.checkUserExist(toUserId)){
            return new BaseResponse<>(USER_ID_NOT_EXIST);
        }

        Long fromUserId = jwtService.getUserIdx();

        if(toUserId==fromUserId){
            return new BaseResponse<>(USER_ID_CANNOT_FOLLOW);
        }

        if(followService.checkFollow(fromUserId,toUserId)==1){
            return new BaseResponse<>(USER_ID_FOLLOW_EXISTS);
        }else{
            followService.follow(fromUserId,toUserId);
            return new BaseResponse<>("구독을 완료했습니다.");
        }

    }catch (BaseException exception) {
        return new BaseResponse<>((exception.getStatus()));
    }
}

@PostMapping("/follow/postunfollow/{toUserId}")
public BaseResponse<?> PostUnFollow(@PathVariable("toUserId") long toUserId)
throws BaseException{
    try{
        if (!userService.checkUserExist(toUserId)){
            return new BaseResponse<>(USER_ID_NOT_EXIST);
        }
        Long fromUserId = jwtService.getUserIdx();

        if(toUserId==fromUserId){
            return new BaseResponse<>(USER_ID_CANNOT_FOLLOW);
        }

        if(followService.checkFollow(fromUserId,toUserId)==1){
            followService.unFollow(fromUserId,toUserId);
            return new BaseResponse<>("구독취소를 완료했습니다.");

        }else{
            return new BaseResponse<>(USER_ID_UNFOLLOW_EXISTS);

        }

    }catch (BaseException exception) {
        return new BaseResponse<>((exception.getStatus()));
    }
}

@PostMapping("/follow/{toUserId}")
public BaseResponse<?> FollowToggle(@PathVariable("toUserId") long toUserId)
throws BaseException {

    if (!userService.checkUserExist(toUserId)){
        return new BaseResponse<>(USER_ID_NOT_EXIST);
    }

    try{
        Long fromUserId = jwtService.getUserIdx();

        if(toUserId==fromUserId){
            return new BaseResponse<>(USER_ID_CANNOT_FOLLOW);
        }

        String returnMessage = (followService.checkFollow(fromUserId,toUserId)==1)?
                "id:"+ fromUserId + "님이 " + "id:" + toUserId + "님을 구독취소했습니다.":
                "id:" + fromUserId + "님이 " + "id:"+toUserId + "님을 구독했습니다.";



        if(followService.checkFollow(fromUserId,toUserId)==1){
            followService.unFollow(fromUserId,toUserId);
        }else{
            followService.follow(fromUserId,toUserId);
        }

        FollowDto followDto = new FollowDto(fromUserId,toUserId);

        return new BaseResponse<>(returnMessage,followDto);

    }catch (BaseException exception) {
        return new BaseResponse<>((exception.getStatus()));
    }
}

}

 

2. FollowService 구현

// FollowService.java

@RequiredArgsConstructor
@Service
public class FollowService {

    private final FollowRepository followRepository;
    
    @Transactional
    public void follow(long fromUserId,long toUserId){

        followRepository.mFollow(fromUserId,toUserId);
    }


    @Transactional
    public void unFollow(Long fromUserId,Long toUserId){

        followRepository.mUnFollow(fromUserId,toUserId);
    }

    @Transactional
    public int checkFollow(Long fromUserId, Long toUserId) {

        return followRepository.checkFollow(fromUserId,toUserId);
    }
}

 

3. FollowRepo 구현

public interface FollowRepository extends JpaRepository<Follow,Long> {

    @Modifying
    @Query(value="INSERT INTO Follow(fromUserId,toUserId,createdAt,status,updatedAt) VALUES(:fromUserId,:toUserId,now(),'ACTIVE',now())",nativeQuery = true)
    void mFollow(long fromUserId,long toUserId);

    @Modifying
    @Query(value = "DELETE FROM Follow WHERE fromUserId = :fromUserId AND toUserId =:toUserId",nativeQuery = true)
    void mUnFollow(Long fromUserId,Long toUserId);

    @Query(value = "SELECT EXISTS(select * from Follow where fromUserId=:fromUserId and toUserId = :toUserId)",nativeQuery = true)
    int checkFollow(Long fromUserId, Long toUserId);

    @Query(value = "SELECT COUNT(*) FROM Follow WHERE fromUserId = :principalId AND toUserId = :pageUserId",nativeQuery = true)
    int followState(long principalId,long pageUserId);

    @Query(value = "SELECT COUNT(*) FROM Follow WHERE fromUserId=:pageUserId",nativeQuery = true)
    int followingCount(long pageUserId);

    @Query(value = "SELECT COUNT(*) FROM Follow WHERE toUserId=:pageUserId",nativeQuery = true)
    int followerCount(long pageUserId);


}

● Like 기능 구현

 

1. like api Controller 구현

@RestController
@RequestMapping("/app/users")
public class PostController {

    private final UserService userService;
    private final PostService postService;
    private final S3Service s3Service;
    private final JwtService jwtService;
    private final LikeService likeService;

    @Autowired
    public PostController(UserService userService,
    PostService postService, S3Service s3Service,
    JwtService jwtService, LikeService likeService) {
        this.userService = userService;
        this.postService = postService;
        this.s3Service = s3Service;
        this.jwtService = jwtService;
        this.likeService = likeService;
    }

...
@PostMapping("/like/{postId}")
public BaseResponse<?> likes(@PathVariable long postId){

    try{

        // 주소의 유저번호가 없으면 에러
        if (!postService.checkPostExist(postId)){
            return new BaseResponse<>(POST_ID_NOT_EXISTS);
        }

        Long loginUserId = jwtService.getUserIdx();

        // 게시물 작성자와 좋아요 유저가 같으면 에러
        if (postService.getPostWriter(postId)==loginUserId) {
            return new BaseResponse<>(POST_CANNOT_MYSELF);

        }

        likeService.Like(postId,loginUserId);

    } catch (BaseException exception) {
        return new BaseResponse<>((exception.getStatus()));
    }
    return new BaseResponse<>("좋아요 요청에 성공했습니다.");
}

@PostMapping("/unlike/{postId}")
public BaseResponse<?> unlikes(@PathVariable long postId){

    try{
        // 주소의 유저번호가 없으면 에러
        if (!postService.checkPostExist(postId)){
            return new BaseResponse<>(POST_ID_NOT_EXISTS);
        }

        Long loginUserId = jwtService.getUserIdx();

        likeService.unLike(postId,loginUserId);

    } catch (BaseException exception) {
        return new BaseResponse<>((exception.getStatus()));
    }
    return new BaseResponse<>("좋아요 취소 요청에 성공했습니다.");
	}
}

 

 

2. LikeService 구현


@RequiredArgsConstructor
@Service
public class LikeService {

    private final LikeRepository likeRepository;
    @Transactional
    public void Like(long postId,long loginUserId) {likeRepository.postLike(postId,loginUserId);}

    @Transactional
    public void unLike(long postId,long loginUserId) {likeRepository.postUnLike(postId,loginUserId);}


    @Transactional
    public long countPostLikes(long postId){
        return likeRepository.countBypostId(postId);
    }


}

 

 

3. LikeRepo 구현

// LikeRepository.java
public interface LikeRepository extends JpaRepository<PostLike,Long> {
    @Modifying
    @Query(value="INSERT INTO postLike(postId,userId,updatedAt,createdAt,status)
    VALUES(:postId,:loginUserId,now(),now(),'ACTIVE')",nativeQuery = true)
    int postLike(long postId,long loginUserId);

    @Modifying
    @Query(value = "DELETE FROM postLike WHERE postId = :postId AND userId= :loginUserId",
    nativeQuery = true)
    int postUnLike(long postId,long loginUserId);

    Long countBypostId(long postId);

}