반응형

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

 

현재 정보

- 몽고 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;
    }

완성된 코드이다.

반응형

+ Recent posts