스프링

뉴스피드 프로젝트 친구설정

148june 2025. 4. 8. 13:25

1. Friend

package org.example.snsprojcet.friend.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.example.snsprojcet.friend.enums.FriendStatus;

@NoArgsConstructor
@Getter
@Entity
@Table(name = "friend")
public class Friend {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    //친구 요청 보내는 사람
    @ManyToOne
    @JoinColumn(name = "userrequest_id",nullable = false)
    private User userrequest;

    //받는사람
    @ManyToOne
    @JoinColumn(name = "userreceiver_id",nullable = false)
    private User userreceiver;

    public Friend(User userrequest, User userreceiver, FriendStatus status) {
        this.userrequest = userrequest;
        this.userreceiver = userreceiver;
        this.status = status;
    }

    @Enumerated(EnumType.STRING)
    private FriendStatus status;

    //친구수락
    public void accept() {
        this.status = FriendStatus.ACCEPTED;
    }

    //친구 거절
    public void reject() {
        this.status = FriendStatus.REJECTED;
    }
}

2. user 요구하는거

package org.example.snsprojcet.friend.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@Entity
@Table(name ="user")
public class User {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    public User(String username) {
        this.username = username;
    }

    public User(Long id) {
        this.id = id;
    }
}

 

유저 id, username호출

 

3.FriendStaus

package org.example.snsprojcet.friend.enums;

public enum FriendStatus {
    PENDING,//대기
    ACCEPTED,//수락
    REJECTED//거절
}

dto

4.FriendRequestDto

package org.example.snsprojcet.friend.dto;

import lombok.Getter;

@Getter
public class FriendRequestDto {
    private Long receiverId;
}

 

5. FriendResponseDto

package org.example.snsprojcet.friend.dto;

import org.example.snsprojcet.friend.entity.Friend;
import org.example.snsprojcet.friend.entity.User;

public class FriendResponseDto {
    private Long id;
    private Long requesterId;
    private Long receiverId;
    private String status;
    private String username;

    public FriendResponseDto(Friend friend) {
        this.id = friend.getId();
        this.requesterId = friend.getUserrequest().getId();
        this.receiverId = friend.getUserreceiver().getId();
        this.status = friend.getStatus().name();
    }
    public FriendResponseDto(Long id, String username) {
        this.id = id;
        this.username = username;
    }

    public static FriendResponseDto fromUser(User user) {
        return new FriendResponseDto(user.getId(), user.getUsername());
    }
}

 

6.FriendRepository

package org.example.snsprojcet.friend.repository;

import org.example.snsprojcet.friend.entity.Friend;
import org.example.snsprojcet.friend.entity.User;
import org.example.snsprojcet.friend.enums.FriendStatus;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface FriendRepository extends JpaRepository<Friend,Long> {

    //요청 보내는 리스트
    List<Friend> findByUserrequest(User userrequest);

    //요청 받는 리스트
    List<Friend> findByUserreceiver(User userreciever);

    //친구 조회
    List<Friend> findAcceptedFriends(FriendStatus friendStatus, User user);
}

7. FriendService

package org.example.snsprojcet.friend.service;

import lombok.RequiredArgsConstructor;
import org.example.snsprojcet.friend.entity.Friend;
import org.example.snsprojcet.friend.entity.User;
import org.example.snsprojcet.friend.enums.FriendStatus;
import org.example.snsprojcet.friend.repository.FriendRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class FriendService {

    private final FriendRepository friendRepository;

    // 친구 요청 보내기
    public Friend sendFriendRequest(User requester, User receiver) {
        return friendRepository.save(new Friend(requester, receiver, FriendStatus.PENDING));
    }

    // 친구 수락
    @Transactional
    public void acceptFriendRequest(Long friendId) {
        Friend friend = friendRepository.findById(friendId)
                .orElseThrow(() -> new IllegalArgumentException("친구 요청이 존재하지 않습니다."));
        friend.accept();
    }

    // 친구 거절
    @Transactional
    public void rejectFriendRequest(Long friendId) {
        Friend friend = friendRepository.findById(friendId)
                .orElseThrow(() -> new IllegalArgumentException("친구 요청이 존재하지 않습니다."));
        friend.reject();
    }

    // 내가 요청한 친구 목록
    public List<Friend> getSentRequests(User user) {
        return friendRepository.findByUserrequest(user);
    }

    // 내가 받은 친구 요청 목록
    public List<Friend> getReceivedRequests(User user) {
        return friendRepository.findByUserreceiver(user);
    }
    // 친구 목록 조회
    public List<User> getFriendList(User user) {
        List<Friend> friends = friendRepository.findAcceptedFriends(FriendStatus.ACCEPTED, user);

        return friends.stream()
                .map(f -> f.getUserrequest().equals(user) ? f.getUserreceiver() : f.getUserrequest())
                .collect(Collectors.toList());
    }

    //친구삭제 및 확인
    public void deleteFriend(Long friendId, User currentUser) {
        Friend friend = friendRepository.findById(friendId)
                .orElseThrow(() -> new RuntimeException("친구 관계를 찾을 수 없습니다."));

        if (!friend.getUserrequest().equals(currentUser) && !friend.getUserreceiver().equals(currentUser)) {
            throw new RuntimeException("이 친구 관계에 없는 사람입니다.");
        }

        if (friend.getStatus() != FriendStatus.ACCEPTED) {
            throw new RuntimeException("수락된 친구만 삭제할 수 있습니다.");
        }

        friendRepository.delete(friend);
    }
}

9.FriendController

package org.example.snsprojcet.friend.controller;

import lombok.RequiredArgsConstructor;
import org.example.snsprojcet.friend.dto.FriendRequestDto;
import org.example.snsprojcet.friend.dto.FriendResponseDto;
import org.example.snsprojcet.friend.entity.Friend;
import org.example.snsprojcet.friend.entity.User;
import org.example.snsprojcet.friend.service.FriendService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/friends")
@RequiredArgsConstructor
public class FriendController {

    private final FriendService friendService;

    // 친구 요청 보내기
    @PostMapping("/request")
    public ResponseEntity<FriendResponseDto> sendFriendRequest(@RequestBody FriendRequestDto dto, User user) {
        User loginUser  = getLoginUser(user); // 로그인 사용자 받아오기
        User receiver = getUserById(dto.getReceiverId()); // 수신자 유저 받아오기

        Friend friend = friendService.sendFriendRequest(user, receiver);
        return ResponseEntity.ok(new FriendResponseDto(friend));
    }

    // 친구 수락
    @PostMapping("/{friendId}/accept")
    public ResponseEntity<String> accept(@PathVariable Long friendId) {
        friendService.acceptFriendRequest(friendId);
        return ResponseEntity.ok("친구 요청을 수락했습니다.");
    }

    // 친구 거절
    @PostMapping("/{friendId}/reject")
    public ResponseEntity<String> reject(@PathVariable Long friendId) {
        friendService.rejectFriendRequest(friendId);
        return ResponseEntity.ok("친구 요청을 거절했습니다.");
    }
    // 친구 삭제
    @DeleteMapping("/{friendId}")
    public ResponseEntity<String> deleteFriend(@PathVariable Long friendId, User user) {
        User loginUser  = getLoginUser(user);
        friendService.deleteFriend(friendId, loginUser);
        return ResponseEntity.ok("친구가 삭제되었습니다.");
    }

    // 보낸 요청 목록
    @GetMapping("/sent")
    public ResponseEntity<List<FriendResponseDto>> sentRequests(User user) {
        User loginUser  = getLoginUser(user);
        List<FriendResponseDto> list =
                friendService
                        .getSentRequests(user)
                        .stream()
                        .map(FriendResponseDto::new)
                        .collect(Collectors.toList()
                );
        return ResponseEntity.ok(list);
    }

    // 받은 요청 목록
    @GetMapping("/received")
    public ResponseEntity<List<FriendResponseDto>> receivedRequests(User user) {
        User loginUser  = getLoginUser(user);
        List<FriendResponseDto> list = friendService.getReceivedRequests(loginUser)
                .stream().map(FriendResponseDto::new).collect(Collectors.toList());
        return ResponseEntity.ok(list);
    }
    
    @GetMapping("/{friendId}/list")
    public ResponseEntity<List<FriendResponseDto>> getFriendList(User user) {
        User loginUser  = getLoginUser(user);
        List<User> friends = friendService.getFriendList(loginUser);

        List<FriendResponseDto> list = friends.stream()
                .map(FriendResponseDto::fromUser)
                .collect(Collectors.toList());

        return ResponseEntity.ok(list);
    }

    // 실제 구현 시에는 로그인 유저 정보나 UserService에서 받아와야 함 수정 해야하는 사항 이름 가져오기
    private User getLoginUser(User user) {
        //  UserService에서 가져와야 함
        return new User(user.getUsername());
        // userservice.findByUserName()그런식으로
    }
    //임시 수신자 정보 가져오기
    private User getUserById(Long id) {
        // 실제로는 UserService 또는 Repository 통해 조회
        // 필요 시 수정 userservice.findById()든
        return new User(id);
    }
}