2023

Stomp convertAndSend

Lahezy 2023. 4. 2.
728x90

이전 글 참고 

2023.03.24 - [2023] - [TIL] stomp origin문제, socket에서의 JWT 처리

 
어제 하다가 만 채팅 시스템에서 구독 시에 과거의 기록이 있다면 조회하는 기능을 추가하였다.
일단. 맞는지 모르겠다. 나중에 공부하다 더 좋은 방법이 있으면 변경해서 진행해야 할 것 같다.
 
우선 백엔드에서는 config파일을 일부 수정하였다.(1명에게만 보내는 경우 /user로 전송하여 처리하였다)
그리고 입장시에 구독을 확인하고 구독이 되어있다면 이전 채팅 기록을 불러오도록 했다.(채팅 기록은 데이터 베이스에 저장되어있다)
계속 LazyInitializationException가 발생해서 transaction이 유지되지 못한다는 글을 보고 임시로 어노테이션을 달아두었다. 
 
convertAndSendToUser해당 메서드로 실제로 한 명에게 원하는 정보를 보내는 경우 사용하는 것 같은데 어떻게 해도 되지 않아서 이 부분도 convertAndSend로 수정해서 진행했다 
그리고 프론트 엔드에서는 해당 정보를 파싱 하여 세팅하는 방식으로 진행하였다. 
 
메세지 타입도 추가해서 입퇴장 시에는 카카오톡처럼 표기하도록 수정하였다.

//webSocketConfig.java파일이다.
@Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/sub","/user");
        registry.setApplicationDestinationPrefixes("/pub");
        registry.setUserDestinationPrefix("/user");
    }
@RestController
@RequiredArgsConstructor
@Slf4j
public class ChatdataController {
    private final SimpMessageSendingOperations sendingOperations;
    private final MemberChatroomService memberChatRoomService;
    private final MemberService memberService;
    private final ChatdataService chatDataService;
    private final ChatroomService chatRoomService;

    //pub으로 받고 sub로 보낸다
    @Transactional
    @MessageMapping("/chat/enter")
    public void enter(ChatDataRequestDto message) {
        log.info("enter: {}", message);
        message.setMessage(message.getWriter() + "님이 입장 하셨습니다");

        Member member = memberService.findByNickname(message.getWriter());
        Chatroom room = chatRoomService.findRoomByRoomId(message.getRoomId());

        //구독이 되어있는 경우
        if (memberChatRoomService.checkMemberChatroom(member, room)) {
            // 해당 방의 이전 채팅 기록 가져오기
            List<ChatDataResponseDto> chatList = new ArrayList<>();
            MemberChatroom mcr = memberChatRoomService.findMemberChatroom(member, room);
            List<Chatdata> allChatList = chatDataService.findAllChatByRoomIdAndDate(room, mcr.getDate());
            if (allChatList != null) {
                chatList = allChatList.stream().map(ChatDataResponseDto::convertToDto).collect(Collectors.toList());
            }

            sendingOperations.convertAndSend("/user/" + message.getWriter() + "/sub/chat/enter/" + message.getRoomId(), chatList); //해당 url을 구독하고 있는 사람들에게 전송
            log.info("지난 기록 전송 완료: {}", chatList);
        } else {
            //구독
            log.info("구독 하였습니다.");
            memberChatRoomService.subscribe(member, room);

            // 입장 메시지 추가
            Chatdata save = chatDataService.save(message, MessageType.ENTER);
            ChatDataResponseDto nowEnter = convertToDto(save);
            sendingOperations.convertAndSend("/sub/chat/" + message.getRoomId(), nowEnter);
        }

    }

    //구독을 취소하지 않고 방을 나가는 경우
    @MessageMapping("/chat/out")
    public void out(ChatDataRequestDto message) {
        log.info("out: {}", message);
    }


    //구독을 취소하고 방을 나가는 경우
    @MessageMapping("/chat/subscribe/out") //유저가 보낸 메세지를 받는다.
    public void subscribeOut(ChatDataRequestDto message) {
        log.info("out: {}", message);

        //방을 나가면서 구독 자체를 취소하도록 한다.
        Member member = memberService.findByNickname(message.getWriter());
        Chatroom room = chatRoomService.findRoomByRoomId(message.getRoomId());

        //구독 취소
        memberChatRoomService.disSubscribe(member, room);

        //퇴장 문구
        message.setMessage(message.getWriter() + "님이 퇴장 하셨습니다");
        Chatdata save = chatDataService.save(message, MessageType.EXIT);
        ChatDataResponseDto chatDataResponseDto = convertToDto(save);
        sendingOperations.convertAndSend("/sub/chat/" + message.getRoomId(), chatDataResponseDto);
    }

    //채팅을 보내는 
    @MessageMapping(value = "/chat/send")
    public void message(ChatDataRequestDto message) {
        log.info("out: {}", message);
        Chatdata save = chatDataService.save(message, MessageType.BASIC);
        ChatDataResponseDto chatDataResponseDto = convertToDto(save);

        sendingOperations.convertAndSend("/sub/chat/" + message.getRoomId(), chatDataResponseDto);
    }

}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatDataResponseDto {
    private String messageType;
    private String roomId;
    private String writer;
    private String message;
    private String time;

    //chatdata 를 저장
    public static ChatDataResponseDto convertToDto(Chatdata chatData) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm");
        String formatedNow = chatData.getDate().format(formatter);
        return new ChatDataResponseDto(chatData.getMessageType().toString(), chatData.getChatroom().getRoomId(), chatData.getWriter(), chatData.getMessage(), formatedNow);
    }

}
    const destination = "/user/" + authCtx.userObj.nickname + "/sub/chat/enter/" + roomId;
    const subscribe = async () => {
        console.log(destination);
        client.current?.subscribe(destination, (body) => {
            const chatlist = JSON.parse(body.body);
            console.log("과거기록 들어옴" + chatlist);

            setMessages(
                chatlist.map(
                    (chat: { roomId: any; writer: any; message: any; time: any }) => ({
                        roomId: chat.roomId,
                        writer: chat.writer,
                        message: chat.message,
                        time: chat.time,
                    })
                )
            );
        });

        client.current?.subscribe("/sub/chat/" + roomId, (body) => {
            const parsed_body = JSON.parse(body.body);
            const {messageType, roomId, writer, message, time} = parsed_body; // 파싱된 정보를 추출
            console.log(parsed_body);
            const nameM = writer + "님: " + message;

            const newMessage: ChatMessage = {
                messageType: messageType,
                roomId: roomId,
                writer: writer,
                message: message,
                time: time,
            };

            console.log("subscribe " + nameM);
            setMessages((_chat_list) => [
                ..._chat_list,
                newMessage, // 파싱된 정보를 새로운 메시지 객체에 담아서 추가
            ]);
            findRoomDetail();
        });
    };

[react를 찍먹중입니다.. 이후에 더욱이 좋은 코드로 수정된다며 수정하여 업로드하겠습니다 ㅠㅜㅠㅜ]
 
조언, 지적은 언제나 감사합니다🙇🏻‍♀️🙇🏻🙇🏻‍♂️
 
github(전체코드) : https://github.com/juhee77/share-anything

 

GitHub - juhee77/share-anything: 개인 토이 프로젝트, 게시판

개인 토이 프로젝트, 게시판. Contribute to juhee77/share-anything development by creating an account on GitHub.

github.com

 

728x90

'2023' 카테고리의 다른 글

[0406]  (0) 2023.04.07
[0405] TIL  (0) 2023.04.06
[0404] TIL  (0) 2023.04.05
[TIL]0327 : ERD(식별관계),@PrePersist  (0) 2023.03.28
[TIL] stomp origin문제, socket에서의 JWT 처리  (0) 2023.03.24

댓글