프로젝트 진행한다고 너무 바빠서 이제야 블로그에 글을 쓴다.
처음 팔로우와 팔로워를 생각 할 때 인스타
를 생각했다. 내 기준 이상적인 팔로우와 팔로잉 시스템을 가지고 있다고 생각했기 때문이다. 그래서 단순히 팔로워 숫자만 있는 것이 아니라 여기에 팔로우를 한 사람을 추가해서 사람을 타고타고 더 다양한 사람
을 볼 수 있지 않을까 하는 마음이었다.
@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);
}
@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;
}
}
이로써 팔로우, 팔로워의 설명이 끝났다. 거의 코드 내에 설명을 작성해 놔서 따로 부가 설명할게 별로 없었던 듯 하다.