WebRTC를 이용한 화면 공유

이진호·2024년 1월 8일
2

최종프로젝트

목록 보기
3/18
post-thumbnail

최종 프로젝트에서 화면을 공유하는 시스템을 만들기 위해서 WebRTC를 이용해서 P2P 통신을 도전했다.

중간에 굉장히 핑퐁거리는 것이 많기 때문에 하면서 조금 많이 헷갈렸던 만큼 정리를 할려고 한다.
일단, WebRTC의 PeerConnection을 할 수 있는 서버를 express와 socket을 이용하여 구현을 했다.

일련의 과정들을 설명하기 전에 몇 가지 용어에 대해서 정해야 한다면 다음과 같다

  • 클1 : 화면을 공유하고 싶은 클라이언트
  • 클2 : 화면을 공유받고 싶은 클라이언트
  • peerConnection : WebRTC 기술에서 사용하는 P2P통신을 위한 클래스
  • offer : 클1이 제공해야 하는 객체
  • answer : 클2가 제공해야 하는 객체

연결을 하는 일련의 과정은 다음과 같다

  1. 클1에서 화면 공유를 시작한다
  2. 화면 공유를 시작하면 peerConnection을 생성한 뒤에 해당 stream을 peerConnection에 넣는다
  3. peerConnection에서 offer를 만들고 localDescription으로 세팅을 한다.
  4. peerConnection에 track 정보를 넘긴다. 이때 track은 video등에 대한 내용이 포함된 것 같다..
  5. offer를 socket을 통해서 전송을 하고 클2에게 전달한다.
  6. 클2가 offer를 받으면 peerConnection을 생성한 뒤에 remoteDescription에 해당 정보를 세팅한다.
  7. 클2는 만들어진 peerConnection을 이용하여 answer라는 객체를 만들고 이를 다시 socket을 통해서 클1에게 전달을 한다.
  8. 클1는 클2로부터 받은 answer객체를 remoteDescription으로 세팅을 한다.

이렇게하면 서로 연결이 되고, 데이터를 주고 받을 수 있게 된다. 이제부터 peerConnection 이벤트를 통해서 조작을 하면된다.
사실 말로 설명하는 것보다는 코드를 하나하나 뜯어보면서 보는게 더 이해가 쉬울 것 같다.

  1. 클1에서 화면 공유를 시작한다. mediaStream에는 video 정보가 담긴다. 이 다음 5번까지 진행하면 된다.
const handleStartCapture = async () => {
  try {
    const mediaStream : MediaStream = await navigator.mediaDevices.getDisplay({
      video: {
        displaySurface: 'window',
      },
      audio: false,
    });
	mediaStream.getTracks().forEach((track) => {
      peerConnection.addTrack(track,mediaStream);
    });
    
	const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(new RTCSessionDescription(offer));
    socket.emit('offer', offer);
    
  } catch(err) {
    console.error('on error when start capture', err);
  }
}
  1. server에서 받은 offer를 클2에게 제공한다.
socket.on('offer', (offer) => {
  socket.broadcast.emit('offer',offer);
})
  1. 이제 6번에서 7번 처리를 하면 된다.
useEffect(() => {
  socket.on('offer', async (offer: RTCSessionDescription) => {
	peerConnection.setRemoteDescription(offer);
    const answer = await peerConnection.createAnswer();
    peerConnection.setLocalDescription(new RTCSessionDescription(answer));
    socket.emit('answer',answer);
  });
},[]);
  1. server에서 받은 answer를 다시 클1에게 제공한다.
socket.on('answer', (answer) => {
  	socket.broadcast.emit('answer',answer);
})
  1. 이제 8번을 처리한다.
useEffect(() => {
	socket.on('answer', async (answer: RTCSessionDescription) => {
      await peerConnection.setRemoteDescription(answer);
    });
},[]);

이런 방식으로 서로 핑퐁하면서 peer to peer 연결을 하면 된다.
이미 작성한 코드를 그대로 가져오기에는 그 서로 주고 받는 느낌이 제대로 살지 않을 것 같아서 일부러 코드를 하나하나 쳤는데 다음에 봤을 때 이해가 더 잘됐으면 좋겠다.

profile
dygmm4288

0개의 댓글