project/모임웹프로젝트

실시간 채팅 구현 백엔드 구현하기 좋아요 누르고 채팅방 저장하기

naspeciallist 2024. 11. 25. 17:53

 

좋아요 누르고 채팅방 저장하기 버튼을 누르게 되면 현재 하고 있었던 채팅을 저장 한 뒤에 상대방에게 좋아요표시를 할 수 있는 기능을 구현 해 보았습니다.

 

먼저 서비스로직부터 작성해 보겠습니다.

 

먼저 좋아요 기능입니다.

public void likeUserByUidAndId(String likerUid, Long likedUserId) {
    // liker는 UID로 조회
    User liker = userRepository.findByUid(likerUid)
            .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다: " + likerUid));
    // likedUser는 ID로 조회
    User likedUser = userRepository.findById(likedUserId)
            .orElseThrow(() -> new RuntimeException("대상 사용자를 찾을 수 없습니다: " + likedUserId));

    // 이미 좋아요를 눌렀는지 확인
    if (!likedUserRepository.existsByLikerAndLikedUser(liker, likedUser)) {
        // 좋아요 기록이 없으면 새롭게 저장
        LikedUser likedUserEntity = LikedUser.builder()
                .liker(liker)
                .likedUser(likedUser)
                .likedAt(LocalDateTime.now())
                .build();

        likedUserRepository.save(likedUserEntity); // 좋아요 기록 저장
    }
}

 

좋아요를 누른 사람과 좋아요를 받은 사람의 uid,id값을 받아 좋아요 기록을 데이터 베이스에 추가하는 로직입니다.

boolean existsByLikerAndLikedUser(User liker, User likedUser);

 

LikedUserRepository의 existByLikerAndLikeUser를 통해 좋아요를 이미 했는지 확인을 먼저 한 뒤 안했으면 LikedUserEntity에 저장하는 방식입니다.

 

좋아요한 사람과 상대방을 저장 할 수 있는 LikedUser Entity를 구성해줍니다.

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class LikedUser {

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

    // 누가 좋아요를 눌렀는지 (User)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "liker_id")
    @JsonIgnore
    private User liker;

    // 누구를 좋아했는지 (User)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "liked_id")
    @JsonIgnore
    private User likedUser;

    private LocalDateTime likedAt; // 좋아요를 누른 시간
}

 

User Entity와 일대다 관계를 맺고 있습니다.

 

User Entity에도 관계를 맺기 위해 아래와 같은 코드를 추가해줍니다.

// 내가 좋아요를 누른 사용자 목록 (양방향 관계 설정)
@OneToMany(mappedBy = "liker", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<LikedUser> likedUsers = new ArrayList<>();

// 나를 좋아요한 사용자 목록
@OneToMany(mappedBy = "likedUser", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<LikedUser> likedByUsers = new ArrayList<>();

 

이제 controller를 구성해줍니다. 

@PostMapping("/likeAndSave/{roomId}")
public ResponseEntity<ChatRoomDTO> likeAndSaveRoom(
        @PathVariable Long roomId,
        @RequestBody Map<String, Object> payload) {

    // likerUid는 String으로 받아서 처리
    String likerUid = (String) payload.get("likerUid"); // 좋아요를 누른 사용자의 UID
    Object likedUserIdObj = payload.get("likedUserId");


    // likedUserId는 String으로 받을 수 있으므로 Long으로 변환
    String likedUserIdStr = (String) payload.get("likedUserId"); // 좋아요를 받은 사용자의 ID(String)
    Long likedUserId = null;

    try {
        likedUserId = Long.parseLong(likedUserIdStr); // String을 Long으로 변환
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("Invalid likedUserId: " + likedUserIdStr);
    }

    // 로그로 확인
    log.info("Liker UID: {}", likerUid);
    log.info("Liked User ID: {}", likedUserId);

    // 1. 좋아요 기록을 저장 (likerUid는 String, likedUserId는 Long)
    userService.likeUserByUidAndId(likerUid, likedUserId);

    // 2. 현재 채팅방을 저장
    chatRoomService.saveChatRoom(roomId);

    // 3. 새로운 사용자와 매칭하여 새로운 채팅방 생성 (likerUid를 넘김)
    ChatRoomDTO newChatRoom = chatRoomService.matchAndCreateNewRoom(likerUid);

    // 4. 새로운 채팅방 정보 반환
    return ResponseEntity.ok(newChatRoom);

 

컨트롤러를 구성하였습니다. 좋아요기록과 채팅방을 저장 한 뒤 새로운 사용자를 매칭하여 새로운 채팅방을 생성합니다. 글을 쓰다가 생각났는데 그냥 저장메소드를 만들지 말고 메세지기록만 삭제안하면 되는데 이걸 더 복잡하게 했습니다. 나중에 리펙토링 과정에서 수정을 해보겠습니다.

function likeAndSaveChatRoom() {
    fetch(`/chat/likeAndSave/${roomId}`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            likerUid: loggedInUserId,   // 현재 로그인된 사용자의 uid
            likedUserId: otherUserId    // 상대방의 사용자 id
        })
    })
        .then(response => {
            if (!response.ok) {
                throw new Error('좋아요 및 채팅방 저장에 실패했습니다.');
            }
            return response.json();
        })
        .then(data => {
            if (data && data.roomid) {
                // 새로운 채팅방 정보로 UI 및 WebSocket, 채팅 기록 업데이트
                updateChatRoom(data.roomid, data.otherUser, data.profileImageUrls);
            } else {
                console.error("새로운 상대를 찾을 수 없습니다.");
            }
        })
        .catch(error => {
            alert(error.message);
            console.error('Error liking and saving chat room:', error);
        });
}

이렇게 js 코드를 통해 프런트에서 요청을 할 수 있게 구성한다면 좋아요 누르고 저장하기 기능을 구성 할 수 있습니다.

추후 저장한 채팅방과 좋아요 확인은 마이페이지를 구성할 때 확인 할 수 있게 하겠습니다.