WebRTC 시작하기

WebRTC는 개방적이고 방해 없는 웹을 위한 장기적인 전쟁의 새로운 분야입니다.

브렌던 에이크, JavaScript 발명가

플러그인 없는 실시간 통신

휴대전화, TV, 컴퓨터가 공통의 플랫폼에서 통신할 수 있는 세상을 상상해 보세요. 웹 앱에 영상 채팅과 P2P 데이터 공유를 쉽게 추가할 수 있다고 상상해 보세요. 이것이 WebRTC의 비전입니다.

이용해 보시겠습니까? WebRTC는 데스크톱 및 모바일의 Chrome, Safari, Firefox, Opera를 통해 사용할 수 있습니다. 먼저 appr.tc의 간단한 영상 채팅 앱부터 시작하는 것이 좋습니다.

  1. 브라우저에서 appr.tc를 엽니다.
  2. 참여를 클릭하여 채팅방에 참여하고 앱에서 웹캠을 사용할 수 있도록 합니다.
  3. 페이지 끝에 표시된 URL을 새 탭에서 열거나 다른 컴퓨터에서 엽니다.

빠른 시작

이 도움말을 읽을 시간이 없거나 코드만 사용하고 싶으신가요?

또는 간단한 신호 서버를 포함하여 완전한 영상 채팅 앱을 빌드하는 방법을 설명하는 단계별 안내인 WebRTC Codelab으로 바로 이동하세요.

WebRTC의 매우 짧은 역사

웹의 마지막 주요 과제 중 하나는 음성과 영상을 통한 인간 커뮤니케이션을 가능하게 하는 것입니다. 실시간 커뮤니케이션, 즉 RTC가 바로 RTC입니다. 웹 앱에서 RTC는 텍스트 입력에 텍스트를 입력하는 것만큼 자연스러워야 합니다. 그렇지 않으면 사람들이 상호 작용할 수 있는 새로운 방법을 개발하고 혁신하는 데 한계가 있습니다.

지금까지 RTC는 기업적이고 복잡하여 값비싼 오디오 및 동영상 기술의 라이선스를 받거나 자체 개발해야 했습니다. 특히 웹에서 RTC 기술을 기존 콘텐츠, 데이터 및 서비스와 통합하는 것은 어렵고 시간이 많이 소요되었습니다.

Gmail 영상 채팅은 2008년에 인기를 얻었으며 2011년 Google은 Gmail과 마찬가지로 토크를 사용하는 행아웃을 출시했습니다. Google은 코덱, 에코 제거 기술 등 RTC에 필요한 여러 구성요소를 개발한 회사인 GIPS를 인수했습니다. Google은 GIPS에서 개발한 기술을 오픈소스로 제공하고 업계의 합의를 위해 인터넷 엔지니어링 태스크포스 (IETF) 및 월드와이드웹 컨소시엄 (W3C)의 관련 표준 기구와 협력했습니다. 2011년 5월에 Ericsson은 WebRTC를 최초로 구현했습니다.

WebRTC는 플러그인이 없는 실시간 동영상, 오디오 및 데이터 커뮤니케이션을 위한 개방형 표준을 구현했습니다. 정말 필요했습니다.

  • 많은 웹 서비스에서 RTC를 사용했지만, 다운로드, 네이티브 앱 또는 플러그인이 필요했습니다. 여기에는 Skype, Facebook, 행아웃이 포함됩니다.
  • 플러그인 다운로드, 설치 및 업데이트는 복잡하고 오류가 발생하기 쉬우며 성가신 작업입니다.
  • 플러그인은 배포, 디버그, 문제 해결, 테스트, 유지 관리가 어려우며 라이선스 및 비용이 많이 드는 복잡한 기술과 통합해야 할 수 있습니다. 사람들이 처음부터 플러그인을 설치하도록 설득하기 어려울 때가 많습니다.

WebRTC 프로젝트의 기본 원칙은 API가 오픈소스여야 하고, 무료이며, 표준화되고, 웹브라우저에 내장되어 있고, 기존 기술보다 더 효율적이어야 한다는 것입니다.

여기가 어디죠?

WebRTC는 Google Meet과 같은 다양한 앱에서 사용됩니다. 또한 WebRTC는 WebKitGTK+ 및 Qt 네이티브 앱과 통합되었습니다.

WebRTC는 다음 세 가지 API를 구현합니다. - MediaStream (getUserMedia라고도 함) - RTCPeerConnection - RTCDataChannel

API는 다음 두 가지 사양으로 정의됩니다.

세 가지 API 모두 Chrome, Safari, Firefox, Edge, Opera를 통해 모바일과 데스크톱에서 지원됩니다.

getUserMedia: 데모 및 코드는 WebRTC 샘플을 참고하거나 웹 오디오의 입력으로 getUserMedia를 사용하는 크리스 윌슨의 놀라운 예를 사용해 보세요.

RTCPeerConnection: 간단한 데모 및 모든 기능을 갖춘 영상 채팅 앱을 보려면 각각 WebRTC 샘플 피어 연결appr.tc를 참고하세요. 이 앱은 WebRTC 커뮤니티의 도움을 받아 Google에서 유지관리하는 JavaScript shim인 adapter.js를 사용하여 브라우저 차이와 사양 변경사항을 추상화합니다.

RTCDataChannel: 실제 동작을 확인하려면 WebRTC 샘플을 참고하여 데이터 채널 데모 중 하나를 확인하세요.

WebRTC Codelab에서는 세 가지 API를 모두 사용하여 영상 채팅 및 파일 공유를 위한 간단한 앱을 빌드하는 방법을 보여줍니다.

첫 번째 WebRTC

WebRTC 앱은 다음과 같은 몇 가지 작업을 실행해야 합니다.

  • 스트리밍 오디오, 동영상 또는 기타 데이터를 가져옵니다.
  • IP 주소 및 포트와 같은 네트워크 정보를 가져오고 다른 WebRTC 클라이언트 (피어라고 함)와 교환하여 NAT 및 방화벽을 통해서도 연결을 사용 설정합니다.
  • 신호 통신을 조정하여 오류를 보고하고 세션을 시작하거나 종료합니다.
  • 해상도 및 코덱과 같은 미디어 및 클라이언트 기능에 관한 정보를 교환합니다.
  • 스트리밍 오디오, 동영상 또는 데이터를 전달합니다.

스트리밍 데이터를 획득하고 통신하기 위해 WebRTC는 다음 API를 구현합니다.

  • MediaStream에서 사용자의 카메라 및 마이크와 같은 데이터 스트림에 액세스할 수 있습니다.
  • RTCPeerConnection를 사용하면 암호화 및 대역폭 관리 기능으로 음성 또는 영상 통화를 할 수 있습니다.
  • RTCDataChannel를 사용하면 일반 데이터의 P2P 통신을 사용할 수 있습니다.

(WebRTC의 네트워크 및 신호 측면에 대해서는 나중에 자세히 논의합니다.)

MediaStream API (getUserMedia API라고도 함)

MediaStream API는 동기화된 미디어 스트림을 나타냅니다. 예를 들어 카메라 및 마이크 입력에서 가져온 스트림에 동영상 및 오디오 트랙이 동기화되었습니다. MediaStreamTrack완전히 다른 요소인 <track> 요소와 혼동하지 마세요.

MediaStream API를 이해하는 가장 쉬운 방법은 아마도 API를 직접 확인하는 것입니다.

  1. 브라우저에서 WebRTC 샘플 getUserMedia로 이동합니다.
  2. Console을 엽니다.
  3. 전역 범위에 있는 stream 변수를 검사합니다.

MediaStream에는 getUserMedia()에서 생성된 MediaStream인 입력과 동영상 요소 또는 RTCPeerConnection에 전달될 수 있는 출력이 있습니다.

getUserMedia() 메서드는 MediaStreamConstraints 객체 매개변수를 사용하고 MediaStream 객체로 확인되는 Promise를 반환합니다.

MediaStream에는 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'와 같은 label가 있습니다. MediaStreamTrack 배열은 getAudioTracks()getVideoTracks() 메서드에서 반환됩니다.

getUserMedia 예에서 stream.getAudioTracks()는 오디오가 없으므로 빈 배열을 반환하며 작동하는 웹캠이 연결되어 있다고 가정하면 stream.getVideoTracks()는 웹캠의 스트림을 나타내는 하나의 MediaStreamTrack 배열을 반환합니다. 각 MediaStreamTrack에는 종류 ('video' 또는 'audio'), label (예: 'FaceTime HD Camera (Built-in)')가 있으며 오디오 또는 동영상으로 구성된 하나 이상의 채널을 나타냅니다. 이 경우 동영상 트랙은 하나뿐이지만 오디오는 없지만 전면 카메라, 후면 카메라, 마이크에서 스트림을 가져오는 채팅 앱과 화면을 공유하는 앱과 같이 더 많은 사용 사례를 상상하기 쉽습니다.

srcObject 속성을 설정하여 MediaStream를 동영상 요소에 연결할 수 있습니다. 이전에는 src 속성을 URL.createObjectURL()로 만든 객체 URL로 설정하여 이 작업을 수행했지만 이 기능은 지원 중단되었습니다.

getUserMediaWeb Audio API의 입력 노드로도 사용할 수 있습니다.

// Cope with browser differences.
let audioContext;
if (typeof AudioContext === 'function') {
  audioContext = new AudioContext();
} else if (typeof webkitAudioContext === 'function') {
  audioContext = new webkitAudioContext(); // eslint-disable-line new-cap
} else {
  console.log('Sorry! Web Audio not supported.');
}

// Create a filter node.
var filterNode = audioContext.createBiquadFilter();
// See https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section
filterNode.type = 'highpass';
// Cutoff frequency. For highpass, audio is attenuated below this frequency.
filterNode.frequency.value = 10000;

// Create a gain node to change audio volume.
var gainNode = audioContext.createGain();
// Default is 1 (no change). Less than 1 means audio is attenuated
// and vice versa.
gainNode.gain.value = 0.5;

navigator.mediaDevices.getUserMedia({audio: true}, (stream) => {
  // Create an AudioNode from the stream.
  const mediaStreamSource =
    audioContext.createMediaStreamSource(stream);
  mediaStreamSource.connect(filterNode);
  filterNode.connect(gainNode);
  // Connect the gain node to the destination. For example, play the sound.
  gainNode.connect(audioContext.destination);
});

Chromium 기반 앱 및 확장 프로그램에는 getUserMedia도 통합할 수 있습니다. 매니페스트에 audioCapture 또는 videoCapture 권한을 추가하면 설치 시 한 번만 권한을 요청하고 부여할 수 있습니다. 그 후에는 사용자에게 카메라 또는 마이크 액세스 권한을 요청하지 않습니다.

getUserMedia()에 대한 권한은 한 번만 부여하면 됩니다. 처음에는 브라우저의 정보 표시줄에 허용 버튼이 표시됩니다. getUserMedia()에 대한 HTTP 액세스는 강력한 기능으로 분류되어 2015년 말 Chrome에서 지원 중단되었습니다.

이는 잠재적으로 카메라나 마이크뿐만 아니라 모든 스트리밍 데이터 소스에 MediaStream를 사용 설정하는 것입니다. 이렇게 하면 저장된 데이터나 센서나 기타 입력과 같은 임의의 데이터 소스에서 스트리밍이 가능해집니다.

getUserMedia()는 다른 JavaScript API 및 라이브러리와 함께 사용할 수 있습니다.

  • 웹캠 장난감은 WebGL을 사용하여 로컬로 공유하거나 저장할 수 있는 사진에 기이하고 멋진 효과를 추가하는 포토부스 앱입니다.
  • FaceKatheadtrackr.js로 빌드된 얼굴 추적 게임입니다.
  • ASCII 카메라는 캔버스 API를 사용하여 ASCII 이미지를 생성합니다.
idevelop.ro/ascii-camera에서 생성된 ASCII 이미지
gUM ASCII 아트!

제약조건

Constraints를 사용하여 getUserMedia()의 동영상 해상도 값을 설정할 수 있습니다. 또한 가로세로 비율, 방향 모드 (전면 또는 후면 카메라), 프레임 속도, 높이, 너비, applyConstraints() 메서드와 같은 다른 제약 조건을 지원할 수 있습니다.

예시는 WebRTC 샘플 getUserMedia: 해상도 선택을 참고하세요.

허용되지 않는 제약 조건 값을 설정하면 예를 들어 요청된 해상도를 사용할 수 없는 경우 DOMException 또는 OverconstrainedError이 제공됩니다. 실제 동작을 확인하려면 데모의 WebRTC 샘플 getUserMedia: 해결 방법 선택을 참고하세요.

화면 및 탭 캡처

또한 Chrome 앱에서는 chrome.tabCapturechrome.desktopCapture API를 통해 단일 브라우저 탭 또는 전체 데스크톱의 실시간 동영상을 공유할 수 있습니다. (데모 및 자세한 내용은 WebRTC를 사용한 화면 공유를 참고하세요. 이 기사는 몇 년 된 기사이지만 여전히 흥미롭습니다.)

실험용 chromeMediaSource 제약 조건을 사용하여 Chrome에서 화면 캡처를 MediaStream 소스로 사용할 수도 있습니다. 화면 캡처에는 HTTPS가 필요하며, 이 게시물에서 설명한 대로 명령줄 플래그를 통해 사용 설정되기 때문에 개발 시에만 사용해야 합니다.

신호: 세션 제어, 네트워크, 미디어 정보

WebRTC는 RTCPeerConnection를 사용하여 브라우저(피어라고도 함) 간에 스트리밍 데이터를 통신하지만 통신을 조정하고 제어 메시지를 전송하는 메커니즘(신호라고도 함)도 필요합니다. 신호 방식 및 프로토콜은 WebRTC에서 지정하지 않습니다. 신호는 RTCPeerConnection API에 포함되지 않습니다.

대신 WebRTC 앱 개발자는 SIP 또는 XMPP와 같이 원하는 메시징 프로토콜과 적절한 이중 (양방향) 통신 채널을 선택할 수 있습니다. appr.tc 예에서는 XHR과 Channel API를 신호 메커니즘으로 사용합니다. CodelabNode 서버에서 실행되는 Socket.io를 사용합니다.

신호는 다음 세 가지 유형의 정보를 교환하는 데 사용됩니다.

  • 세션 제어 메시지: 통신을 초기화하거나 종료하고 오류를 보고합니다.
  • 네트워크 구성: 바깥세상에 대한 컴퓨터의 IP 주소와 포트는 무엇입니까?
  • 미디어 기능: 통신하려는 브라우저 및 브라우저가 처리할 수 있는 코덱과 해상도는 무엇인가요?

P2P 스트리밍을 시작하려면 신호를 통한 정보 교환이 완료되어야 합니다.

예를 들어 앨리스가 철수씨와 대화하고 싶어한다고 가정해 보겠습니다. 다음은 W3C WebRTC 사양의 코드 샘플로, 신호 전달 과정을 보여줍니다. 이 코드는 createSignalingChannel() 메서드에서 생성된 신호 메커니즘이 있다고 가정합니다. 또한 Chrome 및 Opera에서는 현재 RTCPeerConnection가 접두사로 사용됩니다.

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // Send the offer to the other peer.
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// Once remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

먼저 앨리스와 밥은 네트워크 정보를 교환합니다. 후보 찾기 표현식은 ICE 프레임워크를 사용하여 네트워크 인터페이스와 포트를 찾는 프로세스를 의미합니다.

  1. 앨리스는 네트워크 후보를 사용할 수 있을 때 실행되는 onicecandidate 핸들러를 사용하여 RTCPeerConnection 객체를 만듭니다.
  2. 앨리스는 WebSocket 또는 기타 메커니즘과 같이 사용 중인 신호 채널을 통해 직렬화된 후보 데이터를 Bob에게 전송합니다.
  3. 밥은 앨리스로부터 후보 메시지를 받으면 addIceCandidate를 호출하여 원격 동종 앱 설명에 후보를 추가합니다.

WebRTC 클라이언트 (피어 또는 이 예에서는 Alice와 Bob이라고도 함)도 해상도 및 코덱 기능과 같은 로컬 및 원격 오디오 및 동영상 미디어 정보를 확인하고 교환해야 합니다. 미디어 구성 정보를 교환하는 신호는 세션 설명 프로토콜 (SDP)을 사용하여 혜택응답을 교환함으로써 진행됩니다.

  1. 앨리스는 RTCPeerConnection createOffer() 메서드를 실행합니다. 여기서 반환한 결과는 RTCSessionDescription - Alice의 로컬 세션 설명으로 전달됩니다.
  2. 콜백에서 앨리스는 setLocalDescription()를 사용하여 로컬 설명을 설정한 다음 신호 채널을 통해 이 세션 설명을 밥에게 보냅니다. RTCPeerConnectionsetLocalDescription()가 호출될 때까지 후보 수집을 시작하지 않습니다. 이 내용은 JSEP IETF 초안에 성문화되었습니다.
  3. 영수는 setRemoteDescription()를 사용하여 앨리스가 보낸 설명을 원격 설명으로 설정합니다.
  4. 밥은 RTCPeerConnection createAnswer() 메서드를 실행하여 앨리스로부터 받은 원격 설명을 이 메서드에 전달하여 앨리스와 호환되는 로컬 세션을 생성할 수 있도록 합니다. createAnswer() 콜백에는 RTCSessionDescription가 전달됩니다. 영수는 이를 지역 설명으로 설정하고 앨리스에게 보냅니다.
  5. 앨리스는 밥의 세션 설명을 가져오면 setRemoteDescription를 사용하여 이를 원격 설명으로 설정합니다.
  6. 핑!

RTCSessionDescription 객체는 세션 설명 프로토콜(SDP)을 준수하는 blob입니다. 직렬화된 SDP 객체는 다음과 같습니다.

v=0
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126

// ...

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh810

네트워크 및 미디어 정보의 획득과 교환은 동시에 이루어질 수 있지만, 피어 간의 오디오 및 비디오 스트리밍이 시작되기 전에 두 프로세스가 모두 완료되어야 합니다.

앞서 설명한 오퍼/응답 아키텍처를 JavaScript 세션 설정 프로토콜(JSEP)이라고 합니다. (Ericsson의 데모 동영상에는 최초 WebRTC 구현을 위한 신호 및 스트리밍 과정을 설명하는 훌륭한 애니메이션이 있습니다.)

JSEP 아키텍처 다이어그램
JSEP 아키텍처

신호 과정이 성공적으로 완료되면 데이터를 호출자와 피호출자 간에 직접 P2P로 스트리밍할 수 있으며, 스트리밍에 실패하는 경우 중간 릴레이 서버를 통해 스트리밍할 수도 있습니다 (자세한 내용은 뒷부분 참고). 스트리밍은 RTCPeerConnection에서 처리합니다.

RTCPeerConnection

RTCPeerConnection는 피어 간 스트리밍 데이터의 안정적이고 효율적인 통신을 처리하는 WebRTC 구성요소입니다.

다음은 RTCPeerConnection의 역할을 보여주는 WebRTC 아키텍처 다이어그램입니다. 보시다시피 녹색 부분은 복잡합니다.

WebRTC 아키텍처 다이어그램
WebRTC 아키텍처 (webrtc.org)

JavaScript 관점에서 이 다이어그램에서 이해해야 할 중요한 점은 RTCPeerConnection가 숨겨진 수많은 복잡성으로부터 웹 개발자를 보호한다는 것입니다. WebRTC가 사용하는 코덱과 프로토콜은 신뢰할 수 없는 네트워크에서도 실시간 통신을 가능하게 하기 위해 많은 작업을 수행합니다.

  • 패킷 손실 은닉
  • 에코 제거
  • 대역폭 적응성
  • 동적 잡음 버퍼링
  • 입력 신호량 자동 조절
  • 노이즈 감소 및 제거
  • 이미지 정리

이전의 W3C 코드는 신호의 관점에서 WebRTC의 간단한 예를 보여줍니다. 다음은 작동하는 두 WebRTC 앱을 둘러봅니다. 첫 번째는 RTCPeerConnection를 보여주는 간단한 예시이고 두 번째는 완전히 작동하는 영상 채팅 클라이언트입니다.

서버가 없는 RTCPeerConnection

다음 코드는 한 웹페이지에 로컬 원격 RTCPeerConnection (및 로컬 및 원격 동영상)이 있는 WebRTC 샘플 피어 연결에서 가져온 것입니다. 이는 호출자와 피호출자가 같은 페이지에 있는 등 별로 유용하지 않습니다. 하지만 페이지의 RTCPeerConnection 객체가 중간 신호 메커니즘을 사용하지 않고도 데이터와 메시지를 직접 교환할 수 있으므로 RTCPeerConnection API의 작동이 좀 더 명확해집니다.

이 예에서 pc1는 로컬 피어 (호출자)를 나타내고 pc2는 원격 피어 (피호출자)를 나타냅니다.

발신자

  1. RTCPeerConnection를 만들고 getUserMedia()의 스트림을 추가합니다. ```js // 서버는 선택적 구성 파일입니다. (나중에 TURN 및 STUN에 대한 논의를 참조하세요.) pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().foreach((track) => { pc1.addTrack(track, localStream); });
  1. 혜택을 만들고 pc1의 로컬 설명으로, pc2의 원격 설명으로 설정합니다. 호출자와 피호출자가 동일한 페이지에 있으므로 신호를 사용하지 않고 코드에서 직접 실행할 수 있습니다. js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

피호출자

  1. pc2를 만들고 pc1의 스트림이 추가되면 동영상 요소에 표시합니다. js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection API 및 서버

실제로는 WebRTC가 아무리 간단하더라도 서버가 필요합니다. 따라서 다음과 같은 상황이 발생할 수 있습니다.

  • 사용자는 서로를 발견하고 이름과 같은 실제 세부정보를 교환합니다.
  • WebRTC 클라이언트 앱 (피어)은 네트워크 정보를 교환합니다.
  • 피어는 동영상 형식, 해상도 등 미디어에 관한 데이터를 교환합니다.
  • WebRTC 클라이언트 앱은 NAT 게이트웨이 및 방화벽을 통과합니다.

즉, WebRTC에는 다음 네 가지 유형의 서버 측 기능이 필요합니다.

  • 사용자 검색 및 커뮤니케이션
  • 신호
  • NAT/방화벽 순회
  • P2P 통신 실패 시 릴레이 서버

NAT 통과, P2P 네트워킹, 사용자 검색 및 신호를 위한 서버 앱 빌드 요구사항은 이 문서에서 다루지 않습니다. ICE 프레임워크에서 STUN 프로토콜과 확장 프로그램인 TURN을 사용하여 RTCPeerConnection이 NAT 순회 및 기타 네트워크 변칙에 대처할 수 있도록 한다고 말할 수 있습니다.

ICE는 두 개의 영상 채팅 클라이언트와 같은 피어를 연결하기 위한 프레임워크입니다. 처음에 ICE는 UDP를 통해 가장 짧은 지연 시간으로 피어를 직접 연결하려고 시도합니다. 이 프로세스에서 STUN 서버는 NAT 뒤의 피어가 공개 주소와 포트를 찾을 수 있도록 하는 단일 작업을 담당합니다. STUN 및 TURN에 대한 자세한 내용은 WebRTC 앱에 필요한 백엔드 서비스 빌드를 참조하세요.

연결 후보 찾기
연결 후보 찾기

UDP에 실패하면 ICE는 TCP를 시도합니다. 특히 엔터프라이즈 NAT 통과와 방화벽으로 인해 직접 연결이 실패할 경우 ICE는 중개 (릴레이) TURN 서버를 사용합니다. 즉, ICE는 먼저 UDP와 함께 STUN을 사용하여 피어를 직접 연결하고, 실패하면 TURN 릴레이 서버로 대체합니다. 후보 찾기 표현식은 네트워크 인터페이스 및 포트를 찾는 프로세스를 나타냅니다.

WebRTC 데이터 경로
WebRTC 데이터 경로

WebRTC 엔지니어 Justin Uberti는 2013 Google I/O WebRTC 프레젠테이션에서 ICE, STUN, TURN에 대한 자세한 정보를 제공합니다. (프레젠테이션 슬라이드는 TURN 및 STUN 서버 구현의 예를 보여줍니다.)

간단한 영상 채팅 클라이언트

appr.tc의 영상 채팅 데모에서 STUN 서버를 사용한 신호 및 NAT/방화벽 통과 기능을 갖춘 WebRTC를 사용해 볼 수 있습니다. 이 앱은 사양 변경 및 접두사 차이로부터 앱을 격리하는 shim인 adapter.js를 사용합니다.

코드가 로깅에서 의도적으로 장황합니다. 콘솔을 확인하여 이벤트 순서를 알아보세요. 다음은 코드를 자세히 살펴보는 것입니다.

네트워크 토폴로지

현재 구현된 WebRTC는 일대일 통신만 지원하지만, 보다 복잡한 네트워크 시나리오에서는 각각 서로 직접 통신하거나 멀티포인트 제어 장치 (MCU)를 통해 통신하는 등의 더 복잡한 네트워크 시나리오에서 사용할 수 있습니다. MCU는 다수의 참여자를 처리하고 선택적 스트림 전달을 수행할 수 있고 오디오와 동영상의 믹싱 또는 녹음을 수행할 수 있습니다.

멀티포인트 제어 장치 토폴로지 다이어그램
멀티포인트 제어 장치 토폴로지 예시

대부분의 기존 WebRTC 앱은 웹브라우저 간의 통신만 보여주지만, 게이트웨이 서버는 브라우저에서 실행되는 WebRTC 앱이 전화기 (PSTN이라고도 함) 및 VOIP 시스템과 같은 기기와 상호작용하도록 사용 설정할 수 있습니다. 2012년 5월 Doubango Telecom은 iOS 및 Android에서 실행되는 브라우저와 앱 간의 영상 통화를 지원하는 WebRTC 및 WebSocket으로 빌드된 sipml5 SIP 클라이언트를 오픈소스로 공개했습니다. Google I/O에서 Tethr와 Tropo는 WebRTC를 통해 피처폰과 컴퓨터 간 통신을 가능하게 하는 OpenBTS 셀을 사용하여 서류 가방재해 커뮤니케이션을 위한 프레임워크를 시연했습니다. 이동통신사를 사용하지 않는 전화 통신

Google I/O 2012의 Tethr/Tropo 데모
Tethr/Tropo: 서류 가방 속의 재해 커뮤니케이션

RTCDataChannel API<

WebRTC는 오디오 및 동영상은 물론 다른 유형의 데이터에 대한 실시간 통신을 지원합니다.

RTCDataChannel API를 사용하면 지연 시간이 짧고 처리량이 높은 임의 데이터의 P2P 교환이 가능합니다. 단일 페이지 데모와 간단한 파일 전송 앱을 빌드하는 방법을 알아보려면 각각 WebRTC 샘플WebRTC Codelab을 참고하세요.

API의 잠재적인 사용 사례는 다음과 같습니다.

  • 게임
  • 원격 데스크톱 앱
  • 실시간 문자 채팅
  • 파일 전송
  • 분산 네트워크

API에는 RTCPeerConnection를 최대한 활용하고 강력하고 유연한 P2P 커뮤니케이션을 지원하는 여러 기능이 있습니다.

  • RTCPeerConnection 세션 설정 활용
  • 우선순위가 지정된 여러 동시 채널
  • 신뢰할 수 있는 전송 시맨틱스와 불안정한 전송 시맨틱스
  • 기본 제공 보안 (DTLS) 및 정체 제어
  • 오디오 또는 동영상과 함께 사용하거나 사용하지 않고 사용할 수 있는 기능

문법은 send() 메서드 및 message 이벤트가 있는 WebSocket과 의도적으로 유사합니다.

const localConnection = new RTCPeerConnection(servers);
const remoteConnection = new RTCPeerConnection(servers);
const sendChannel =
  localConnection.createDataChannel('sendDataChannel');

// ...

remoteConnection.ondatachannel = (event) => {
  receiveChannel = event.channel;
  receiveChannel.onmessage = onReceiveMessage;
  receiveChannel.onopen = onReceiveChannelStateChange;
  receiveChannel.onclose = onReceiveChannelStateChange;
};

function onReceiveMessage(event) {
  document.querySelector("textarea#send").value = event.data;
}

document.querySelector("button#send").onclick = () => {
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

브라우저 간에 직접 통신이 이루어지므로 방화벽에 대처하기 위해 홀 펀칭이 실패하고 NAT에 실패하는 경우 릴레이 (TURN) 서버가 필요하더라도 RTCDataChannel가 WebSocket보다 훨씬 빠를 수 있습니다.

RTCDataChannel 버전은 Chrome, Safari, Firefox, Opera, 삼성 인터넷에서 사용할 수 있습니다. Cube Slam 게임은 API를 사용하여 게임 상태를 전달합니다. 친구와 어울리거나 곰과 함께 플레이해 보세요. 혁신적인 플랫폼 SharefestRTCDataChannelpeerCDN을 통한 파일 공유를 지원하여 WebRTC가 P2P 콘텐츠 배포를 지원하는 방법을 엿볼 수 있었습니다.

RTCDataChannel에 관한 자세한 내용은 IETF의 초안 프로토콜 사양을 참고하세요.

보안

실시간 커뮤니케이션 앱이나 플러그인은 여러 가지 방법으로 보안을 침해할 수 있습니다. 예를 들면 다음과 같습니다.

  • 암호화되지 않은 미디어나 데이터는 브라우저 간 또는 브라우저와 서버 간에 가로챌 수 있습니다.
  • 앱이 사용자 모르게 동영상이나 오디오를 녹화하고 배포할 수 있습니다.
  • 멀웨어나 바이러스가 무해해 보이는 플러그인이나 앱과 함께 설치될 수 있습니다.

WebRTC에는 이러한 문제를 방지할 수 있는 몇 가지 기능이 있습니다.

  • WebRTC 구현에는 DTLSSRTP와 같은 보안 프로토콜을 사용합니다.
  • 암호화는 신호 메커니즘을 포함한 모든 WebRTC 구성요소에 필수입니다.
  • WebRTC는 플러그인이 아닙니다. 구성요소는 별도의 프로세스가 아닌 브라우저 샌드박스에서 실행됩니다. 구성요소는 별도로 설치할 필요가 없으며 브라우저가 업데이트될 때마다 업데이트됩니다.
  • 카메라 및 마이크 액세스 권한을 명시적으로 부여해야 하며 카메라 또는 마이크가 실행 중이면 사용자 인터페이스에 명확하게 표시됩니다.

스트리밍 미디어의 보안에 대한 자세한 설명은 이 문서의 범위를 벗어납니다. 자세한 내용은 IETF에서 제안한 제안된 WebRTC 보안 아키텍처를 참조하세요.

결론

WebRTC의 API 및 표준은 전화 통신, 게임, 동영상 제작, 음악 제작, 뉴스 수집 등의 콘텐츠 제작 및 커뮤니케이션을 위한 도구를 범용화하고 분산시킬 수 있습니다.

기술은 이보다 더 많이 파괴적을 일으키지 않습니다.

블로거 Phil Edholm은 "잠재적으로 WebRTC와 HTML5를 통해 원래의 브라우저가 정보를 얻기 위해 했던 것과 동일한 변환을 실시간 통신에 사용할 수 있을 것입니다."라고 말했습니다.

개발자 도구

자세히 알아보기

표준 및 프로토콜

WebRTC 지원 요약

MediaStreamgetUserMedia API

  • Chrome 데스크톱 18.0.1008 이상, Android용 Chrome 이상
  • Opera 18 이상, Android 20 이상용 Opera
  • Opera 12, Opera Mobile 12 (Presto 엔진 기반)
  • Firefox 17 이상
  • Microsoft Edge 16 이상
  • iOS의 경우 Safari 11.2 이상, MacOS의 경우 11.1 이상
  • Android의 UC 11.8 이상
  • 삼성 인터넷 4 이상

RTCPeerConnection API

  • Chrome 데스크톱 20 이상, Android용 Chrome 29 이상 (플래그 없음)
  • Opera 18 이상 (기본적으로 사용 설정됨), Android 20 이상용 Opera (기본적으로 사용 설정됨)
  • Firefox 22 이상 (기본적으로 사용 설정됨)
  • Microsoft Edge 16 이상
  • iOS의 경우 Safari 11.2 이상, MacOS의 경우 11.1 이상
  • 삼성 인터넷 4 이상

RTCDataChannel API

  • Chrome 25에서 실험용 버전이지만 Chrome 26 이상, Android 29 이상에서 더 안정적이고 Firefox 상호 운용성을 제공합니다.
  • Opera 18 이상에서 안정화 버전 (및 Firefox 상호 운용성 포함), Android 20 이상에서 Opera
  • Firefox 22 이상 (기본적으로 사용 설정됨)

getUserMediaRTCPeerConnection와 같은 API의 크로스 플랫폼 지원에 관한 자세한 내용은 caniuse.comChrome 플랫폼 상태를 참고하세요.

RTCPeerConnection용 네이티브 API는 webrtc.org의 문서에서도 확인할 수 있습니다.