[Spring] following, follower

강민승·2023년 8월 10일
0

spring

목록 보기
7/17
post-thumbnail

📌 유저 팔로워와 팔로우 구현하기 !

프로젝트 진행한다고 너무 바빠서 이제야 블로그에 글을 쓴다.

처음 팔로우와 팔로워를 생각 할 때 인스타를 생각했다. 내 기준 이상적인 팔로우와 팔로잉 시스템을 가지고 있다고 생각했기 때문이다. 그래서 단순히 팔로워 숫자만 있는 것이 아니라 여기에 팔로우를 한 사람을 추가해서 사람을 타고타고 더 다양한 사람을 볼 수 있지 않을까 하는 마음이었다.

📌 코드

컨트롤러

@PostMapping("/follow")
	public Response<?> follow(@RequestBody FollowRequestDto followRequestDto, HttpServletRequest httpServletRequest) {
		//Jwt 헤더에서 user 정보 가져오기
		User user = getUser(httpServletRequest);
		
		//Response로 한번 감싸서 return
		return new Response<>("true","follow 성공",userService.follow(followRequestDto));
	}

서비스

public UserResponseDto follow(FollowRequestDto followRequestDto) {
        // user1 이 현재 로그인 한 유저
        User user1 = userRepository.findById(followRequestDto.getFollowerId())
                .orElseThrow(() -> new BadRequestException(ErrorCode.NOT_EXISTS_FOLLOWER));

        // user 2는 내가 팔로잉 할 유저
        User user2 = userRepository.findById(followRequestDto.getFollowingId())
                .orElseThrow(() -> new BadRequestException(ErrorCode.NOT_EXISTS_FOLLOWING));

        // user 1과 user 2가 모두 있다면
        Optional<Follow> optionalFollow = followRepository.findByFollowerAndFollowing(user1, user2);

        // 팔로우 안되어 있으면 팔로우, 팔로우 돼있으면 팔로우 취소
        if (optionalFollow.isEmpty()) {
            Follow follow = Follow.builder()
                    .follower(user1)
                    .following(user2)
                    .build();

            // followRepository에 저장
            followRepository.save(follow);

            // user 1에 팔로잉 목록에 추가, user 2에 팔로워 목록 추가
            user1.addMemberTofollowing(follow);
            user2.addMemberTofollower(follow);
        }
        else {
            // user 1 팔로잉 목록에서 제거, user 2 팔로우 목록에서 제거
            Follow follow = optionalFollow.get();
            user1.removeMemberTofollower(follow);
            user2.removeMemberTofollowing(follow);
            followRepository.deleteByFollowerAndFollowing(user1, user2);
        }

        return UserResponseDto.toUserResponseDto(user1);
    }

Dto

@Getter
@NoArgsConstructor
public class UserResponseDto {
    // pk 값을 id로 받음. 유저 로그인 id를 고유값으로 만들기 위함.
    private String id;

    // 유저 닉네임
    private String nickname;

    // 팔로워 리스트
    private List<String> followers = new ArrayList<>();

    // 팔로잉 리스트
    private List<String> followings = new ArrayList<>();
    
    // 생성자
    @Builder
    public UserResponseDto(String id, String nickname, List<String> followers, List<String> followings) {
        this.id = id;
        this.nickname = nickname;
        this.followers = followers;
        this.followings = followings;
    }

    // user 인스턴스를 UserResponseDto로 변환시키는 로직 
    @Builder
    public static UserResponseDto toUserResponseDto(User user) {

        // lambda를 통해 List
        List<String> followerNames = user.getFollowers().stream()
                .map(follow -> follow.getFollowing().getNickname())
                .collect(Collectors.toList());

        List<String> followingNames = user.getFollowings().stream()
                .map(follow -> follow.getFollower().getNickname())
                .collect(Collectors.toList());

        return new UserResponseDto(
                user.getId(),
                user.getNickname(),
                followerNames,
                followingNames
        );
    }

레포지터리

public interface FollowRepository extends JpaRepository<Follow, Long> {

    Optional<Follow> findByFollowerAndFollowing(User follower, User following);
   
   Long deleteByFollowerAndFollowing(User follower, User following);
}

엔티티

@Entity
@NoArgsConstructor
@Getter
public class Follow {

    // pk 값
    @Id
    @GeneratedValue
    @Column(name = "follow_id")
    private Long id;

    // 양방향 맵핑
    @JsonIgnore // 무한 참조를 방지
    @ManyToOne(fetch = FetchType.LAZY) // 성능 최적화를 위함.
    @JoinColumn(name = "follower_id")
    private User follower;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "following_id")
    private User following;

    @Builder
    public Follow(Long id, User follower, User following) {
        this.id = id;
        this.follower = follower;
        this.following = following;
    }
}

이로써 팔로우, 팔로워의 설명이 끝났다. 거의 코드 내에 설명을 작성해 놔서 따로 부가 설명할게 별로 없었던 듯 하다.

profile
Step by Step goes a long way. 꾸준하게 성장하는 개발자 강민승입니다.

0개의 댓글