공부메모 & 오류해결/Spring Boot

[Spring Boot + Websocket] 웹소켓을 사용한 채팅방 기능에서 사용자 정보 가져오기

남건욱 2023. 9. 12. 02:19

목차

    반응형

    알림 기능을 구현 중이다. 현재 프로젝트에 웹소켓을 통한 다른 유저들과의 채팅이 가능한 상태이다. 나는 메시지가 전송되면 메시지를 받는 유저에게 알림을 받도록 하려고 생각했다. 금방 구현할 줄 알았지만 복잡한 부분이 많았다. 

     

    현재 정보

    - 몽고 DB에 채팅내역 저장

    - private_chat_room DB에서 1:1 채팅 시 id값, title(랜덤), user1, user2의 정보가 들어있음

     

        public PrivateChatMessageResponseDto savePrivateChatMessage(PrivateChatMessageRequestDto chatMessageRequestDto) {
            User user = userRepository.findByUsername(chatMessageRequestDto.getUsername()).orElseThrow();
            PrivateChatMessage chatMessage = new PrivateChatMessage(chatMessageRequestDto, user);
            mongoTemplate.save(chatMessage, chatMessageRequestDto.getTitle().toString());
            PrivateChatMessageResponseDto message = new PrivateChatMessageResponseDto(chatMessage);
            message.updateUrl(user.getProfileUrl());
            return message;
        }

    기존의 savePrivateChatMessage 메서드이다. 

     

     

             String notificationContent = user.getNickname() + "님이 메시지를 보냈습니다.";
                    String notificationUrl = "/api/chatRooms/" + chatMessageRequestDto.getTitle().toString();
                    notificationService.oneMessgeNotification(받을 유저의id, notificationContent, notificationUrl);

    여기서 나는 미리 구현해 둔 위와 같은 코드를 추가하여 알림 기능을 추가하려 하였다.

     

     

       // 개인 메시지 알림 생성 및 전송
        public void oneMessgeNotification(Long userId, String inviteAuthor, String url){
            Notification notification = new Notification();
            LocalDateTime currentTime = LocalDateTime.now(); // 현재 시간 가져오기
            notification.setCreatedAt(currentTime); // 생성 시간 설정
            notification.setUserId(userId);
            notification.setContent("\uD83D\uDCE71:1 메시지 알림\uD83D\uDCE7<br>" + inviteAuthor);
            notification.setUrl(url);
            notification.setRead(false);
            notification.setType("1:1 messge");
    
            notificationRepository.save(notification);
            sendNotificationToUser(userId, notification);
        }

    oneMessgeNotification 메서드이다.

     

    우선 간단하게 받을 유저의 정보를 가져오려 하였다. 하지만 아무리 시도해도 보내는 유저의 값은 찾기가 쉬운데 받는 유저의 정보는 어디에도 존재하지 않았다. 그러던 중 만들어둔 테이블이 떠올랐다. 

     

    이런 식으로 채팅방이 만들어지면 유저 1, 유저 2의 이메일 주소를 저장하고 id값, title값을 랜덤으로 지정해 주는 방식이었다.

     

     

        @Query("SELECT p.user1 FROM PrivateChatRoom p WHERE p.title = :title")
        Optional<String> findUser1ByTitle(@Param("title") String title);
    
        @Query("SELECT p.user2 FROM PrivateChatRoom p WHERE p.title = :title")
        Optional<String> findUser2ByTitle(@Param("title") String title);

    그래서 우선 해당 레포지토리에 title값을 넣으면 유저의 정보를 가져올 수 있도록 두 개의 메서드를 생성했다.

     

     

          Optional<String> user1Optional = privateChatRoomRepository.findUser1ByTitle(message.getTitle());
          Optional<String> user2Optional = privateChatRoomRepository.findUser2ByTitle(message.getTitle());
          
                String user1 = user1Optional.get();
                String user2 = user2Optional.get();

    그다음 타이틀을 넘겨줘서 해당 타이틀에 포함된 유저 1, 유저 2의 정보를 가져온 후. get()을 사용해서 user1, user2에 넣어줬다.

     

     

    if (user1Optional.isPresent() && user2Optional.isPresent()) {
                String user1 = user1Optional.get();
                String user2 = user2Optional.get();
    
                // 현재 사용자와 user1, user2를 비교하여 알림을 보냅니다.
                if (!user.getUsername().equals(user1)) {
                    User user1Hello = userRepository.findUserIdByUsername(user1).orElseThrow(
                            () -> new IllegalArgumentException("존재하지 않는 유저입니다.")
                    );
                    String notificationContent = user.getNickname() + "님이 메시지를 보냈습니다.";
                    String notificationUrl = "/api/chatRooms/" + chatMessageRequestDto.getTitle().toString();
                    notificationService.oneMessgeNotification(user1Hello.getId(), notificationContent, notificationUrl);
                }
    
                if (!user.getUsername().equals(user2)) {
                    User user2Hello = userRepository.findUserIdByUsername(user2).orElseThrow(
                            () -> new IllegalArgumentException("존재하지 않는 유저입니다.")
                    );
                    String notificationContent = user.getNickname() + "님이 메시지를 보냈습니다.";
                    String notificationUrl = "/api/chatRooms/" + chatMessageRequestDto.getTitle().toString();
                    notificationService.oneMessgeNotification(user2Hello.getId(), notificationContent, notificationUrl);
                }
    
            } else {
                // 
            }

    그런 후 처음에 사용하려 했던 작성해 둔 메시지 전송 코드를 넣어주었다. 2명의 유저 중 받는 사람에게 만 알림을 전송해야 하기 때문에 if문으로 두 가지의 경우를 비교해 주었다. 전송하는 유저와 title에 포함된 두 명의 유저를 각각 비교하여 전송하는 유저와 이메일 값이 다를 시 메시지를 전송해 주도록 했다.

     

     

    User user1Hello = userRepository.findUserIdByUsername(user1).orElseThrow(
                            () -> new IllegalArgumentException("존재하지 않는 유저입니다.")
                    );

    중간에 이렇게 유저를 조회해 오는 코드를 작성한 이유는 다음과 같다. 나는 알림을 보낼 때 유저의 id값으로 비교하여 알림을 전송하는 식으로 구현하였다. 하지만 private_chat_room에는 유저의 이메일만 존재한다. 따라서 유저이메일을 넘겨주고 유저 id를 넘겨받은 뒤 알림을 전송하는 메서드에 유저 id값을 넘겨주는 식으로 구성하였다.

     

       /**
         * 개인 채팅방 메세지 저장
         * @param chatMessageRequestDto: 메세지 타입과, 보내는 채팅방의 ID, 유저 정보, 메세지 내용, 보내는 시간을 받아옴
         * @return: ResponseDto에 담아서 반환
         */
        public PrivateChatMessageResponseDto savePrivateChatMessage(PrivateChatMessageRequestDto chatMessageRequestDto) {
            User user = userRepository.findByUsername(chatMessageRequestDto.getUsername()).orElseThrow();
            PrivateChatMessage chatMessage = new PrivateChatMessage(chatMessageRequestDto, user);
            mongoTemplate.save(chatMessage, chatMessageRequestDto.getTitle().toString());
            PrivateChatMessageResponseDto message = new PrivateChatMessageResponseDto(chatMessage);
            message.updateUrl(user.getProfileUrl());
    
            Optional<String> user1Optional = privateChatRoomRepository.findUser1ByTitle(message.getTitle());
            Optional<String> user2Optional = privateChatRoomRepository.findUser2ByTitle(message.getTitle());
    
            if (user1Optional.isPresent() && user2Optional.isPresent()) {
                String user1 = user1Optional.get();
                String user2 = user2Optional.get();
    
                // 현재 사용자와 user1, user2를 비교하여 알림을 보냅니다.
                if (!user.getUsername().equals(user1)) {
                    User user1Hello = userRepository.findUserIdByUsername(user1).orElseThrow(
                            () -> new IllegalArgumentException("존재하지 않는 유저입니다.")
                    );
                    String notificationContent = user.getNickname() + "님이 메시지를 보냈습니다.";
                    String notificationUrl = "/api/chatRooms/" + chatMessageRequestDto.getTitle().toString();
                    notificationService.oneMessgeNotification(user1Hello.getId(), notificationContent, notificationUrl);
                }
    
                if (!user.getUsername().equals(user2)) {
                    User user2Hello = userRepository.findUserIdByUsername(user2).orElseThrow(
                            () -> new IllegalArgumentException("존재하지 않는 유저입니다.")
                    );
                    String notificationContent = user.getNickname() + "님이 메시지를 보냈습니다.";
                    String notificationUrl = "/api/chatRooms/" + chatMessageRequestDto.getTitle().toString();
                    notificationService.oneMessgeNotification(user2Hello.getId(), notificationContent, notificationUrl);
                }
    
            } else {
                // 
            }
    
    
            log.info(message.getTitle());
    
            return message;
        }

    완성된 코드이다.

    반응형
    프로필사진

    남건욱's 공부기록