본문 바로가기
Develop/Zoom만들기

Zoom. 기능 추가사항 ( +오류 해결 )

by 보보트레인 2023. 9. 11.

2023.9.10 수정사항)

방 입장 / 퇴장메시지 전달하기.

 

문제 : 방을 입장할때는 입장했다는 메시지가 출력되는데, 나갈때는 퇴장 메시지 전달 x

 

원인1) : 브라우저1 /브라우저 2 로 접속했을 때, 브라우저2가 나갈 때, 나갔다는 메시지를 브라우저1에게 전달해야함.

하지만 브라우저 2가 나가면 브라우저 2가 해당되어있던 socket자체가 소멸되어 누가 나갔는지 disconnect메서드에 올바른 파라미터(인자)값을 전달할 수 없음.

 

원인2) :  브라우저2가 꺼지면, 저장되어있던 roomName의 값도 소실되어 어느방으로 부터 나갔는지 disconnect메서드에 올바른 인자값을 전달할 수 없음. 

 

 

원인1 해결방법) socket.to로 emit(강제함수실행) 메서드를 보내지 않고 wsServer자체에 값을 보내도록 코드 수정. 왜냐하면 wsServer는 socket들을 관리하는 상위 개념의 서버라 누구 한명의 소켓이 소멸했다고 해서 영향을 받지 않음.

 

원인2 해결방법) roomName을 전역변수로 관리 하였다.

 

→ 다음과 같이 server.js코드 수정

wsServer.on("connection", (socket) => {

    let currentRoom = null;

  socket.on("join_room", (roomName) => {
    socket.join(roomName);
    currentRoom = roomName;
    socket.to(roomName).emit("welcome");
  });
 socket.on('disconnect', () => {
    if(currentRoom !== null){
      wsServer.to(currentRoom).emit('bye');
      currentRoom = null;
    }
  });
});

2023.9.11 수정사항 1)

9/10 의 수정사항은 여전히 중계서버를 거쳐서 해결하는 방식이기에 webRTC를 적극활용하지 못했다.

P2P (Peer To Peer)를 적용하기위해 webRTC의 방식으로의 리팩토링을 하였다.

 

먼저 같은 서버에 접속해 있는 다른 사용자에게 서버를 거치지 말고 P2P 소통을 하자고 제안하는 offer와 answer를 이용하여 방 입장 메시지를 전달하도록했다.

 

webRTC구동순서는이전의 포스팅에서도 말했다시피 간단하게만 설명하면

 

브라우저 1이 접속되어있는 서버에 브라우저 2가 접속했을 때를 가정하면,

1 이 2에게 offer 보냄 → 2가 1에게 answer를 보내고 1이 candidate를 다시 2에게 보냄

 

따라서 offer를 보낸다는 뜻은 누군가가 접속했다는 뜻이고

socket.on("answer", answer => {
  addMessage("someone joined!");
  myPeerConnection.setRemoteDescription(answer);
})

다음과 같이 answer를 받는 메서드에 addMessage("someone joined!"); 를 넣어두면 브라우저 1에게만 누군가 들어왔다는 메시지를 전달할 수 있다.

브라우저 1에게만 방 입장메시지가 잘 뜬다!

 

※만약 answer에 넣지않고 offer메서드에 넣으면 기존 접속자 브라우저1과 신규 접속자 브라우저 2 모두에게 방 입장 메시지가 가게 되니 이는 크나큰 오류로 이어진다!

( offer 객체는 모든 소켓이 보유하는 것이기 때문!  - offer는 p2p를 하겠다는 webRTC입장표와 같은 역할이다!)


2023.9.11 수정사항 2)

webRTC의 myDataChannel을 이용해서 중계서버를 거치지 않고 즉시 송신하는 P2P 채팅기능을 추가하고자 한다.

let myDataChannel;
 
socket.on("welcome", async () => {
  myDataChannel = myPeerConnection.createDataChannel("chat");
  const offer = await myPeerConnection.createOffer();
 ~~ 생략
});

일단 offer를 보내는 브라우저 1에서 offer보다 앞서서 data channel을 만들어주었다.

이제 나중에 접속하는 브라우저 2에서는 data channel을 감지하기만 하면됨 

 

socket.on("offer", async (offer) => {
 
myPeerConnection.addEventListener("datachannel", (event) => {
        myDataChannel = event.channel;
        myDataChannel.addEventListener("message", (event) => {
             //받는사람
            addMessage(`someone : ${event.data}`);
        });
    });
 ~생략
})

받는 쪽에서 datachannel 이벤트를 감지하게 만들었음. 그리고 datachannel의 특징인 .data로 받은 메시지 출력

 

보낸사람도 화면에 보낸메시지가 출력되어야 하니

//submit 메시지 눌렀을때
async function handleMessageSubmit(event){
    event.preventDefault();
    const input = chat.querySelector("input")
    const value = input.value;
    //보낸사람.
    myDataChannel.send(value);
    //보낸사람 화면에 띄울 메시지
    addMessage(`You: ${value}`);
    input.value = "";
}

다음과 같이 myDataChannel로 메시지를 보낸이후 본인화면에도 addMessage메서드를 통해 데이터 통신

 

<결과화면>

보낸사람 화면
받은사람 화면!

webRTC의 datachannel을 통해 중계서버를 거치지않고 바로 메시지를 주고받을 수 있는 peer-to-peer를 구현했다!!

 

반응형