ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 항해99 52일차 TIL : websocket으로 실시간 양방향 통신 테스트 하기.
    항해99_WIL 이따금씩 TIL 2021. 4. 25. 16:42

    이번 미니프로젝트는 중고품 직거래가 컨셉이었다. 그래서 구매희망자와 판매자가 직접 소통하게 하기 위해서 채팅 기능을 넣기로 했다. 처음에는 지난 클론코딩에서 했던 댓글 달기 식으로 하면 되겠거니라고 생각했다. 하지만 아니었다.

     

    왜냐하면 채팅은 양방향 실시간 소통이기 때문에 댓글식의 클라이언트-서버 간의 요청-응답식으로 데이터를 주고 받는 방식이 아니기 때문이다. 그래서 클라이언트-서버 통신에 쓰이는 axios와는 달리 websocket이라는 방식의 실시간 통신 프로토콜을 이용해야 한다.

     

    코드 구현 방식이 막막하기도 했지만, 채팅을 맡은 백엔드분의 도움과 설명으로 일부 해냈는데, 통신이 되었다고 개발자 도구에서 결과가 나올 때는 정말 경이로웠다. 이게 되다니!!!

    그것이 되게 한 코드를 보면서 설명하겠다.

     

    const ChatModal = (props) => {
    
      const dispatch = useDispatch();
    
      let socket = new SockJS("http://52.78.12.253/chatting");
      // const ws = Stomp.over(sock);
      const stompClient = Stomp.over(socket);  // endpoint
    
      const post_list = useSelector((state) => {
          // console.log(state)
          // window.alert('')
          return state.post.detail_list
        });
      const target_idx = post_list.findIndex((p) => p.id == props.detail_id);
      const post_target = post_list[target_idx]
      
      // 이메일 정보
      const receiverEmail = post_target.email;
      const userEmail = localStorage.getItem('email');
      console.log(receiverEmail);
    
      const _token = localStorage.getItem("Authorization");
        let token = {
          headers : { Authorization: `${_token}` }, 
        }
    
      const API = `http://52.78.12.253/api/chat/newChat?receiver=${receiverEmail}&sender=${userEmail}`;
      axios.post(API, token)
        .then((response) => {
          console.log(response.data);
    
          let chatInfo = {
            senderName: response.data.senderName,
            senderEmail: response.data.senderEmail,
            senderId: response.data.senderId,
            receiverName: response.data.receiverName,
          }
    
          console.log(response.data.messages);
          console.log(chatInfo);
          dispatch(chatActions.getChatRoomInfo(chatInfo));
          // }
        }).catch((error) => {
          console.log(error)
          window.alert("채팅 데이터들을 가져오지 못했습니다.")
        })
    
    
      React.useEffect(()=>{
        const userEmail = localStorage.getItem('email');
        console.log(stompClient);
        stompClient.connect({}, function () {
            stompClient.subscribe('/topic/' + userEmail, function (e) {
                if(e.body.toString() == "notice"){
                    // alertClosing('noticeCome',2000);
                }
                else{
                    // alertClosing('comeMessage',2000);
                }
              });
            });
        }, []);
    

     

    그것이 되게 한 코드를 보면서 설명하겠다.설명은 아래 링크의 블로그의 내용을 많이 참고했다.

    postitforhooney.tistory.com/entry/SpringStomp-Spring-stomp%EC%99%80-Socjks%EB%A5%BC-%ED%86%B5%ED%95%9C-%EC%9B%B9%EC%86%8C%EC%BC%93-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%9E%A5%EB%8B%A8%EC%A0%90

     

    먼저

    let socket = new SockJS("http://52.78.12.253/chatting");

    const stompClient = Stomp.over(socket);  // endpoint

    위 두 코드로 먼저 서버의 채팅 API를 잡고,  클라이언트쪽 즉 프론트엔드쪽의 endpoint (통신하는 부분으로 이해했다)를 설정해서 변수에 할당해준다.

     

    그런 다음 클라이언트에 axios로 POST 요청을 해서 통신에 필요한 데이터를 가져온다. sender는 나, 즉 로그인한 사용자이고, receiver는 상품을 등록한 판매자이다. 통신에 필요한 정보는 두 사람 각각의 이메일만 필요한데, 서버에서 가져온 senderName, senderId, receiverName은 대화하는 상대방을 표시해주는 정보로 채팅창에 입력되는 데이터다.

     

    그런 다음, useEffect를 이용해서 그 안의 함수가 실행되면서 실시간 양방향 통신이 시작된다. 프론트엔드는 클라이언트쪽이므로 변수도 stompClient 임에 주목하자.

     

    통신이 되었으면 통신이 된 인증샷도 필요하다. 

    개발자도구_통신인증.jpg

    마지막 부분의 빈 배열은 메시지로, 통신 연결 테스트만 했고 메시지를 주고 받는 준비는 되지 않았기 때문에 빈 배열로 온 것이다. 그래도 이것만으로도 대단히 뿌듯!!!!!!!!!! 이걸 새벽 내내 되게 한다고 고생한 나와 백엔드 능력자님에게 칭찬의 박수를!

     

    + 후일담

    과제 관련해서 다른 것을 해결할게 많아서 시간을 많이 썼는데 그러다보니 과제 제출이 코앞까지 다가왔다. 그리고 내가 채팅 구현 관련해서는 지식이 모자라다 보니 많이 헤매기도 했고 다른 분의 채팅 코드를 많이 참고한다고 그분들 코드를 베껴 놓고 분석은 하긴 했는데 우리와 로직이 달라서 베껴온 코드가 쓸모가 없음을 알게 되었다. 그래서 결과적으로 시간만 낭비한 셈이 되었다. 그래도 할 수 있는데까지는 해보려 했지만 채팅창에 채팅 참가자 이름을 올리는 정도까지만 하고 더 진행하지 못했다. 다음에 기회가 되면 좀더 배워서 해보고 싶다. 다른 프로젝트를 하면서 채팅을 구현 사람들의 코드를 참고하기도 하고 틈틈히 관련 공부도 할 생각이다.

    댓글

금손이 프론트엔드 개발자가 되고자 오늘도 존버중