project/모임웹프로젝트

실시간 채팅 구현 백엔드 구현하기 다른상대 찾기

naspeciallist 2024. 11. 25. 15:30

실시간 채팅 화면입니다. 여기서 다른상대 찾기 버튼을 클릭하면 다른 상대로 바꿀 수 있게 구성을 해보겠습니다.

 

먼저 서비스로직을 구성하겠습니다.

public ChatRoomDTO matchAndCreateNewRoom(String userUid) {

    return matchAndCreateRoom(userUid);
}

 이렇게 uid를 이용하여 전에 구성해 놓았던 메소드인  matchAndCreateRoom(userUid)을 반환하게 해준다.

 

public ChatRoomDTO matchAndCreateRoom(Long userId) {
    User currentUser = userRepository.findById(userId)
            .orElseThrow(() -> new RuntimeException("User not found with userId: " + userId));

    // 현재 사용자의 관심사 목록
    List<String> userInterests = currentUser.getInterests().stream()
            .map(interest -> interest.getInterestName())
            .collect(Collectors.toList());

    // 관심사 목록 중 하나라도 일치하는 사용자 목록 조회 (이미 매칭된 사용자 제외)
    List<User> potentialMatches = userRepository.findUsersByInterestsAndDifferentGender(
            userInterests, currentUser.getId(), currentUser.getGender());

    // 매칭될 사용자가 없을 경우 예외 처리
    if (potentialMatches.isEmpty()) {
        throw new RuntimeException("No matching users found");
    }

    // 랜덤하게 한 명의 사용자를 선택
    User matchedUser = potentialMatches.get(new Random().nextInt(potentialMatches.size()));

    // 새로운 채팅방 생성
    ChatRoom chatRoom = new ChatRoom();
    chatRoom.setUser1(currentUser);
    chatRoom.setUser2(matchedUser);
    chatRoom.setRoomname("Room-" + currentUser.getName() + "-and-" + matchedUser.getName());

    ChatRoom savedRoom = chatRoomRepository.save(chatRoom);
    return entityToDto(savedRoom, matchedUser);
}

private ChatRoomDTO entityToDto(ChatRoom chatRoom, User otherUser) {
    AddUserRequest otherUserDto = userService.convertToDto(otherUser); // User -> AddUserRequest로 변환
    return ChatRoomDTO.builder()
            .roomid(chatRoom.getRoomid())
            .roomname(chatRoom.getRoomname())
            .user1Id(chatRoom.getUser1().getId())  // 현재 사용자 ID
            .user2Id(chatRoom.getUser2().getId())  // 상대방 사용자 ID
            .otherUser(otherUserDto)               // 상대방 정보 추가
            .profileImageUrls(getProfileImageUrls(otherUser))  // 상대방 프로필 이미지 추가
            .build();
}

 

이렇게 기존에 매칭되었던 상대방을 제외하고 repository에 지정해놓았던 알고리즘을 이용하여 새로운 상대방을 매칭하도록 구성을 해보았습니다.

 

그 뒤에 이제 컨트롤러를 구성을 해 보겠습니다.

 

// uid로 다른 상대 찾기
@PostMapping("/findAnotherUser/{userUid}")
public ResponseEntity<ChatRoomDTO> findAnotherUser(@PathVariable String userUid) {
    try {
        // 새로운 상대를 찾고 새로운 채팅방을 생성
        ChatRoomDTO newRoomDTO = chatRoomService.matchAndCreateNewRoom(userUid);

        // 기존 채팅방의 메시지 삭제
        chatMessageService.deleteMessagesByRoomId(newRoomDTO.getRoomid());

 

새로운 상대를 찾도록 서비스코드를 호출해주고 기존에 채팅을 했던 상대방과의 메세지는 삭제하도록 해줍니다.

 

public void deleteMessagesByRoomId(Long roomId) {
    chatMessageRepository.deleteByChatRoomRoomid(roomId);
}

삭제 할 수 있는 서비스코드를 작성해 준 뒤 

// 특정 채팅방에 있는 모든 메시지를 삭제하는 쿼리
@Modifying
@Transactional
@Query("DELETE FROM ChatMessage m WHERE m.chatRoom.roomid = :roomId")
void deleteByChatRoomRoomid(@Param("roomId") Long roomId);

repository에 query문을 작성하여 삭제 할 수 있게 데이터베이스와 연동을 할 수 있게 해줍니다.

 

이제 프런트에서 새로운 상대 찾기를 요청 할 수 있게 스크립트 코드를 짜줍니다.

function findAnotherUser() {
    // 서버로 새로운 상대 찾기 요청
    fetch(`/chat/findAnotherUser/${loggedInUserId}`, {
        method: 'POST'
    })
        .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 finding another user:', error);
        });
}

 

이렇게 새로운 상대 찾기를 구성을 해 보았습니다.