2018 webRTC 정리

web | 19 April 2019

Tags | webrtc js p2p frontend

초안 작성은 ‘코딩 실시간 화상 강의실 서비스’ 를 만들던 2018년 12월 18일인데, 한참 뒤인 2019년 4월 19일에 하게 되었네요. 😂 초안을 작성할 땐 webRTC 세계를 담아보겠다는 포부를 가지고 글을 쓰기 시작했는데, 한참 지난 뒤 글을 적으려다보니 다 까먹어서 내용이 처음에 계획했던 것에 비해 많이 단촐해졌습니다. 하하.

What is WebRTC?

WebRTC 는 브라우저나 모바일 application 에서 Real Time Communication (RTC) 를 편리하게 할 수 있는 api 를 만들고자 하는 목적으로 시작된 프로젝트입니다. Open Project 이지만 (2018년 12월 기준) Google Chrome Team 의 주도로, Mozilla, Opera 등의 단체의 지원을 받으며 진행되고 있습니다.

프로젝트의 진행 방식은, WebRTC API 최신 명세 (SPEC) 를 WebRTC M{xx} 와 같은 이름으로 공개하고, 거의 동시에 Chrome (혹은 Chrome Beta) 에 구현하여 릴리즈하는 것 같습니다. Opera, Safari, Firefox 등의 브라우저들은 이 공개된 명세에 발맞춰 따라옵니다.

WebRTC 로 할 수 있는 일은 굉장히 많지만, 간단한 p2p 영상/음성 연결, p2p 데이터 교환 등에도 많이 쓰입니다.

WebRTC 공식 홈페이지 webrtc.org 링크

WebRTC 의 3가지 API

2018년 말인 현재, 대부분의 브라우저가 webRTC API 표준을 지원합니다.

  1. MediaStream (getUserMedia)
  2. RTCPeerConnection
  3. RTCDataChannel

API 1. MediaStream

사용자의 카메라와 마이크 같은 곳의 데이터 스트림에 접근합니다.

API 2. RTCPeerConnection

암호화 및 대역폭 관리를 하는 기능을 가지고 있고, 오디오 또는 비디오 연결을 합니다.

API 3. RTCDataChannel

일반적인 데이터 P2P통신

webRTC application 이 수행하는 것

  1. Streaming Data (Audio, Video, Text, Data) 를 수집합니다.
    • API : MediaStream, getUserMedia
  2. IP주소, Port등의 네트워크 정보를 수집합니다. 그리고 그 정보를 다른 WebRTC Client (=Peer) 와 교환합니다.
    • No API offered
    • Need Signaling Server
  3. “Error Report”, “Session 초기화”, “Session 종료” 와 같은 신호 통신을 관리해야 합니다.
    • No API offered
    • Need Signaling Server
  4. 해상도와 코덱들 같은 미디어와 클라이언트의 capabilty에 대한 정보를 교환합니다.
    • No API offered
    • Need Signaling Server
  5. 스트리밍 오디오, 비디오 또는 데이터를 주고 받아야합니다.
    • API : RTCPeerConnection, RTCDataChannel

크게 나누면 다음과 같은 세단계로 볼 수 있습니다.

Fetching -> Signaling -> Connection & Communication

이중 Fetching(1) 과 Connection & Communication(5) 단계는 webRTC API 를 이용하지만, 가장 번거로운 Signaling 과정(2,3,4) 는 정작 webRTC API 로 명세되어있지 않습니다. 개발 엔지니어 개인 역량에 따라 구현 형태도 다르고, 정답도 없습니다.

Signaling Stage

Signaling 단계는 서로 다른 두 peer (WebRTC Client) 가 Communication 하기 위한 준비단계로, 3가지 종류의 정보를 교환해야 합니다.

  1. Network 정보를 교환합니다.
    • ICE Framework 를 사용해 find candidate => ip 와 port 를 찾는다
    • 내 ip 와 port 정보
  2. Media Capability 를 교환합니다.
    • sdp (Session Description Protocol) 형식을 따르는 blob 인 offeranswer 를 주고 받으며 교환합니다.
    • 내 브라우저와 상대 peer 브라우저가 사용 가능한 코덱들과 해상도들은 무엇일까
  3. Session Control Messages 교환합니다
    • Session (통신연결) 의 초기화,종료
    • Error Report

1. Network 정보 (ICE Candidate) 교환하기

  1. RTCPeerConnection Object 를 새롭게 생성하고 RTCPeerConnection.onicecandidate 핸들러를 통해 현재 내 client 의 Ice Candidate(Network 정보) 가 확보되면 실행될 callback 을 전달합니다.
  2. Ice Candidate (내 네트워크 정보) 가 확보되면, Signaling Channel 을 통해 상대 peer 에게 serialized 된 ice candidate 정보를 전송합니다. (쌍방이 서로에게 합니다.)
  3. 상대 peer 의 candidate (네트워크 정보) 가 도착하면, RTCPeerConnection.addIceCandidate 를 통해 상대 peer 의 네트워크 정보를 등록합니다. (쌍방이 모두 합니다.)

2.Media Capability 교환하기 + Session Control Message 교환하기

A 와 B 가 webRTC 통신을 하려고합니다. 각자 브라우저에서 RTCPeerConnection 객체를 가지고 있고, 서로의 네트워크 정보 (ice candidate) 를 교환 후 각자의 RTCPeerConnection.addIceCandidate 를 통해 서로의 네트워크 정보를 등록하였습니다.

  1. B 가 RTCPeerConnection.createOffer 를 호출해 Offer SDP (Session Description Protocol) 을 생성합니다. 여기엔 내 브라우저에서 사용 가능한 코덱이나 해상도에 대한 정보가 들어있습니다.
  2. B 가 Offer SDP 를 Signaling Channel 을 통해 전송합니다.
  3. A 는 Signaling Channel 에서 Offer SDP 를 받아, RTCPeerConnection.setRemoteDescription 을 수행합니다.
  4. A 의 RTCPeerConnection 객체는 상대 session 에 대한 정보를 알고 있게 되었고, RTCPeerConnection.createAnswer 를 호출하여 Answer SDP 를 생성하여 Signaling Channel 을 통해 B 에게 전달합니다.
  5. B 도 마찬가지로 자신의 RTCPeerConnection.setRemoteDescription 을 호출해, 전달받은 Answer SDP 를 등록합니다.
  6. A, B 각 측에서 setRemoteDescription 이 성공적으로 수행되었다면, 각 브라우저에서는 서로의 peer 에 대해 인지하고 있는 상태라고 할 수 있고, p2p 연결이 성공적으로 완료되었다고 할 수 있습니다.

Communication Stage

보통 webRTC 를 통해서 peer 와 peer 가 주고받는 데이터는 크게 아래의 두가지입니다.

  1. video 나 audio 데이터 스트림
  2. 직렬화된 text 데이터

교환의 양상은, 연결이 이루어지기 전에 데아터 stream 이나 채널을 미리 준비하고, 연결이 완료되면 데이터를 받았을 때의 callback 을 통해 받은 데이터를 처리합니다. 조금 더 자세한 내용은 아래와 같습니다.

1. video 나 audio 데이터 스트림 의 경우

주는 입장 : 자신의 머신에서 (getUserMedia 등의 api 를 통해) video/audio 스트림 source 를 취득해 RTCPeerConnection 을 생성할 당시에 addTrack(데이터 stream 채널을 연결) 해줍니다. Signaling 을 통해 connection 이 이루어지기 전에 미리 되어야합니다.

받는 입장 : RTCPeerConnection.ontrack 의 callback 을 커스텀하게 설정해서, connection 이 성공적으로 이루어진 후에 상대방의 Track (video/audio stream) 이 감지되면 어떤 동작을 할지 설정할 수 있습니다. 보통 받은 track 의 데이터 스트림을 DOM 의 <video srcObject={??}/> element 에 연결해 보여줍니다.

2. 직렬화된 text 데이터 의 경우

주는 입장 : RTCPeerConnection.createDataChannel 을 통해, 특정 이름의 data 전달 채널을 개설할 수 있습니다. 이 또한 Signaling 을 통해 connection 이 이루어지기 전에 미리 되어야합니다.

받는 입장 : RTCPeerConnection.ondatachannel 의 callback 을 커스텀하게 설정해서, connection 이 성공적으로 이루어진 후에 상대방이 data channel 을 통해 어떤 데이터를 보냈을 때의 동작을 설정할 수 있습니다.

참고한 자료들

Getting Started with webRTC : https://www.html5rocks.com/ko/tutorials/webrtc/basics/