TIL #19 Data Channels [22.07.21]

Ellie·2022년 7월 21일
0

TodayILearned

목록 보기
19/24

저번 시간에 webRTC에 이어 이번에는 Data Channels에 대해 공부해볼 것이다!

🔎 언제 Data Channel를 사용할까?

✔️ Data Channel을 사용할 때

MDN: RTCPeerConnection.createDataChannel()

실시간으로 소통할 때 메시지를 보내고 싶다면 socket.io나 websocket에서는 서버로 텍스트를 보냈었다. 하지만 peer to peer방식인 webRTC에서 서버 없이 메시지를 보내고 싶다면 바로 이때 Data Channel을 이용하면 된다.

물론 텍스트 같은 가벼운 데이터일 경우에만 가능하다. 비디오나 오디오 같은 건 무거워서 안된다고 한다...😅

🔎 Data Channel 사용해보기!

다음은 Data Channel을 이용해 간단한 채팅창을 구현해보려고 한다!

✔️ STEP1 : Data Channel를 생성하는 곳은 createOffer() 메소드를 사용하는 Peer A 브라우저이다.

WebRTC 관련 함수는 이전 WebRTC 포스트를 참고하기! 너무 길어질 것 같아서 여기는 data channel 관련 코드만 적어놓았다. (ex: makeConnection()) WebRTC 포스트

let myPeerConnection;
let myDataChannel;

const chatBox = document.getElementById("form");
const chatInput = chatBox.querySelector("input");

// 메세지를 추가 함수
function addChatMessage(message) {
  const ul = chatBox.querySelector("ul");
  const li = document.createElement("li");
  
  li.innerText = message;
  ul.appendChild(li);
  chatInput.value = "";
}

// 메세지 추가 이벤트리스너 submit
chatBox.addEventListener("submit", (event) => {
  event.preventDefault();
  const message = chatInput.value;
  // Peer A에 나타나는 코드
  addChatMessage(`${nicknameInput.value}: ${message}`);
  // Peer B 브라우저에 나타나는 코드. data channel로 연결되어 있다면 send메소드로 다른 브라우저에 메시지 보내기. 
  if (myDataChannel) { 
    myDataChannel.send(`${nicknameInput.value}: ${message}`);
  }
});

// peer A's code
socket.on("welcome", async (user, newCount) => {
  // data channel code: 여기서 data channel을 생성한다!
  myDataChannel = myPeerConnection.createDataChannel("chat"); 
  myDataChannel.addEventListener("message", (event) => console.log(event.data));
  console.log("made data channel"); // data channel을 만들었다.
  
  // webRTC: create offer code
  const offer = await myPeerConnection.createOffer();
  myPeerConnection.setLocalDescription(offer);
  console.log("sent the offer");
  socket.emit("offer", offer, roomName);
});


// peer B's code
socket.on("offer", async (offer) => {
  // data channel code
  myPeerConnection.addEventListener("datachannel", (event) => {
    myDataChannel = event.channel;
    myDataChannel.addEventListener("message", (event) =>
      addChatMessage(event.data)
    );
  });
  
  // webRTC: receive offer code
  myPeerConnection.setRemoteDescription(offer);
  const answer = await myPeerConnection.createAnswer();
  myPeerConnection.setLocalDescription(answer);
  socket.emit("answer", answer, roomName);
});

socket.on("answer", (answer) => {
  console.log("received the answer");
  myPeerConnection.setRemoteDescription(answer);
});

socket.on("ice", (ice) => {
  console.log("receive the candidate");
  myPeerConnection.addIceCandidate(ice);
});

여기까지 webRTC에서 data channel을 이용하여 채팅하는 법을 공부해보았다. 공부하면서 중간에 비디오 스트림 제어 등등 코드가 복잡해지면서 갑자기 data channel의 상태가 open이 되지 않는 에러가 발생했다. 계속 연결중이라고 뜨고 도저히 원인을 모르겠어서 아예 싹 다 밀고 처음부터 했다는.....😂 😂 다시 하니까 된다. 하루종일 붙잡고 있었던 거 같은데 대체 뭐가 문제였을까................ 아 지금도 원인을 못알아낸게 찝찝하다.


07.27 추가

왜 오류가 났는지 알아냈다!!

다음은 서버 코드이다.

❌
wsServer.on("connection", (socket) => {
  socket.on("join_room", (nickname, roomName) => {
    socket.join(roomName);
    socket["nickname"] = nickname;
    wsServer.to(roomName).emit("welcome", socket.nickname); // 전체 유저에게 보낼 때
  });
});
⭕️
wsServer.on("connection", (socket) => {
  socket.on("join_room", (nickname, roomName) => {
    socket.join(roomName);
    socket["nickname"] = nickname;
    socket.to(roomName).emit("welcome", socket.nickname);
  });
});

서버 소켓에서 나는 전체 유저에게 메시지를 전달하고 싶어서 socket이 아니라 전체 소켓 서버인 wsServer를 사용했다. 그랬더니 오류가 남... 근데 왜 data channel에 오류가 나는지는 모르겠다 ㅠㅠ

+++ 추가
또 알아냈다 ㅋㅋㅋㅋ
위에서 다수의 유저에게 메시지를 보낼 때 data channel에서

Uncaught (in promise) DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: stable

와 같은 오류가 났는데, 이는 2명 이상의 유저에게 채널이 연결되어 불안정하기 때문에 나타나는 오류인 것 같다. data channel은 1대1 환경에서 잘 동작하고 있다.

만약 다수의 유저에게 메시지를 보내는 소켓을 생성하고 싶다면 data channel을 이용하지 않는 소켓에서는 자유롭게 가능한 것 같다. data channel을 사용하는 곳에 사용하면 에러가 났다.

이건 제가 여러 실험을? 통해서 유추해낸 것인데, 혹시 틀렸다면 댓글로 알려주세요😀 감사히 공부하겠습니다😀😀

profile
정말로 아는 것인지 항상 의심하기

0개의 댓글