100초 후 WebRTC: Scratch에서 화상 채팅 앱을 만드는 방법

100초 후 WebRTC: Scratch에서 화상 채팅 앱을 만드는 방법

반응형

WebRTC를 사용하면 브라우저 내에서 친구와 실시간 오디오-비디오 스트림을 교환할 수 있습니다. 홈 붐을 틈타 자신만의 화상 회의 앱을 만들고 싶다면, WebRTC는 여러분이 찾고 있는 API입니다. 두 개 이상의 브라우저가 오디오-비디오 미디어를 타사 서버나 네이티브 앱 없이 바로 교환할 수 있는 피어-투-피어 연결을 설정할 수 있기 때문입니다.

어떻게 작동하는지 살펴봅시다.

첫 번째 피어는 다른 피어가 해당 피어에 연결하도록 요청하는 제안을 생성합니다. 이로 인해 비디오 코덱 타이밍 등과 같은 피어 투 피어 연결을 설명하는 정보가 포함된 SDP 개체 또는 세션 설명 프로토콜이 생성됩니다.

그런 다음 다른 피어가 데이터를 읽어 호출에 응답할 수 있는 서버에 데이터를 저장하고 SDP 응답을 생성하여 서버에 기록합니다. 이 프로세스를 신호라고 하며 타사 서버에서 처리합니다.

신호 서버는 두 당사자가 연결 데이터를 안전하게 교환할 수 있도록 하지만 피어 간에 실제로 전송되는 미디어는 절대 건드리지 않습니다. 하지만 여기서 문제가 발생합니다. 실제 환경의 대부분의 장치는 방화벽 뒤에 배치되며 네트워크 주소 변환으로 인해 IP 주소가 지속적으로 변경됩니다. 따라서 네트워킹 관점에서 피어 투 피어 연결이 복잡해집니다.

하지만 다행히도, 고객이 공용 IP 주소를 찾는 데 도움을 주는 인터랙티브 연결 설정(ICE)이라는 표준이 있습니다. 이제 두 피어 모두 피어 1이 피어 2에 연결하는 데 사용할 수 있는 IP 주소 및 포트를 포함하는 ICE 후보 목록을 생성합니다.

백그라운드에서 WebRTC는 스턴 서버에 일련의 요청을 함으로써 이 작업을 수행합니다. 스턴 서버는 구글과 같은 믿을 수 있는 출처로부터 많은 무료 옵션들이 있기 때문에 당신이 스스로 설정할 필요가 없다. 각 피어는 다른 피어가 읽을 수 있는 자신의 ICE 후보를 데이터베이스에 저장합니다. 그런 다음 알고리즘은 어느 후보가 가장 적합한지를 자동으로 판단하여 어느 시점에 두 피어 간에 실시간 미디어가 흐르기 시작할 수 있는지 확인합니다.

100초만에 WebRTC가 되었습니다.

비디오 채팅 앱을 만드는 방법을 알고 싶으시다면, 지금부터는 저희만의 비디오 채팅 앱을 만들 것이기 때문에 계속 시청해 주시기 바랍니다. 꽤 복잡하게 들릴지 모르지만 WebRTC API는 이 모든 일들이 백그라운드에서 마술처럼 일어나도록 해줍니다.

앞으로 몇 분 동안 바닐라 JavaScript만 사용하여 P2P(Peer-to-Peer) 비디오 통화 앱을 처음부터 구축할 수 있습니다. 신호 서버로 Firebase를 사용합니다.이 기사의 마지막 부분에서는 가정 라이프스타일의 새 작업에 필요한 기능을 실시간으로 구현하는 방법을 배우게 될 것입니다.

먼저 데모를 살펴보겠습니다. 왼쪽에는 로컬 사용자의 비디오 피드가 있고 오른쪽에는 원격 비디오가 있습니다.

로컬 사용자는 먼저 앱에 웹캠 액세스 권한을 부여합니다. 그러면 해당 사용자가 전화를 걸어 제안 세부 정보가 포함된 문서를 Firestore에 작성할 수 있습니다. 동시에 WebRTC 협상 프로세스를 처리하는 피어 연결 인스턴스를 브라우저에 생성할 것입니다. 이 오퍼링은 고유한 ID를 갖게 되며, 이 ID는 세계 어딘가에서 다른 사용자가 액세스할 수 있습니다. 그러면 해당 사용자가 통화에 참여합니다.

그런 다음 고유 ID를 사용하여 사용자는 자신의 피어 연결을 설정하고 응답 상세 내역을 동일한 문서에 작성합니다. 그런 다음 두 피어 모두 ICE 후보를 데이터베이스에 기록합니다. 제안 후보와 답변 후보자를 위한 서브 컬렉션이 하나 있습니다.

이 데이터 모델을 통해 두 피어 간에 신호가 발생할 수 있습니다. 데이터 자체는 말도 안 되는 것처럼 보이지만, IP 주소 포트 쌍이 포함되어 있어 두 피어에서 연결을 설정할 수 있습니다. 이제 두 사용자 모두 이 데이터를 실시간으로 듣고 브라우저에서 WebRTC API를 사용하여 일대일 비디오 채팅 기능을 제공하는 연결을 설정할 수 있습니다. 이제 JavaScript 코드로 이동할 준비가 되었습니다.

처음에는 Vue.js라는 사람이 개발한 매우 간단한 빌드 도구인 "vite"라는 도구를 사용하여 바닐라 JavaScript 프로젝트를 만들었습니다. 명령줄에서 npminitvitejs/app을 실행하여 새 프로젝트를 초기화할 수 있습니다. 기본적으로 웹 팩과 같은 것에 대해 걱정할 필요 없이 종속성을 설치할 수 있는 웹 프로젝트를 제공합니다.

프로젝트를 초기화한 후, 우리는 파이어베이스를 설치해야 합니다. Firebase에는 백엔드 신호 서버로 사용할 수 있는 Firestore 데이터베이스가 포함되어 있습니다. 파이어베이스는 데이터베이스의 업데이트를 실시간으로 쉽게 청취할 수 있기 때문에 신호 서버로서는 탁월한 선택입니다. 기존 데이터베이스로 작업했다면 웹 소켓 같은 것을 구현해야 했을 것입니다. 이 비디오는 20분 정도 소요됩니다.

Firebase 콘솔에서 테스트 모드로 Firestore를 초기화합니다. 그런 다음 설정 패널에서 웹 프로젝트를 생성하고 프로젝트 인증 정보를 가져오십시오.

그런 다음 main.js 파일로 이동할 수 있습니다. Firebase를 가져오고 Firebase 구성으로 앱을 초기화하십시오.

이제 Firebase를 설치했으므로 3가지 글로벌 상태를 초기화하겠습니다. 이러한 값은 Reactor Angular와 같은 UI 프레임워크를 사용하는 경우 여러 구성 요소 간에 공유하고자 하는 값입니다. 첫 번째이자 가장 중요한 값은 rtc 피어 연결입니다. 이 개체는 모든 작업이 발생하는 위치입니다. 데이터베이스를 업데이트하고 연결 자체에 미디어 스트림을 추가할 수 있는 다양한 이벤트를 내보냅니다. 가장 중요한 한 가지는 ICE 후보를 생성하는 것이지만 그러기 위해서는 어떤 서버를 사용할지 알아야 합니다.

세상에는 다양한 옵션이 있지만, 우리는 구글의 무료 옵션들을 사용할 것입니다. 여기에서 각 사용자의 웹캠에서 나오는 비디오 스트림인 로컬 스트림과 원격 스트림에 대한 값을 얻을 수 있습니다.

이제 우리는 바닐라 JavaScript를 사용하고 있으므로 필수 DOM API를 사용해야 합니다. 우리는 document.getElementById를 사용하여 HTML에서 실제 비디오 피드와 UI에서 다양한 상호 작용을 제공하는 버튼을 보여 주는 비디오 요소를 캡처하고 있습니다.

사용자가 가장 먼저 할 일은 웹캠을 여는 버튼을 클릭하는 것이다. 웹캠 버튼의 클릭 이벤트에 대한 이벤트 핸들러를 등록하겠습니다. 사용자의 웹캠에서 스트림을 얻는 것은 매우 쉽습니다. 탐색기.mediaDevices.getUserMedia 메서드를 기다리면 비디오와 오디오를 true로 설정합니다. 그러면 웹캠에 액세스할 수 있는 권한을 사용자에게 요청하는 대화상자가 브라우저에 나타납니다. 이 작업이 완료되면 미디어 스트림 개체로 약속이 해결됩니다.

웹캠에 액세스할 수 있게 되면 여기에 원격 스트림을 설정할 수도 있습니다. 원격 스트림 자체는 빈 미디어 스트림이 됩니다. 이제 두 스트림을 피어 연결에서 사용할 수 있도록 설정하고 DOM의 비디오 요소에 표시해야 합니다.

로컬 스트림이 이미 브라우저에서 실행되고 있습니다. 따라서 트랙을 가져온 다음 해당 트랙을 루프하고 각 트랙에 대해 해당 트랙과 로컬 스트림을 포함한 피어 연결 광고 트랙이라고 부릅니다.

이제 원격 스트림은 현재 비어 있으며 피어 연결 자체에 의해 업데이트되므로 순수 연결에서 트랙 이벤트를 청취한 다음 스트림에서 트랙을 수신하여 루프하고 원격 스트림에 추가할 수 있습니다.

이제 스트림을 관리하는 마지막 단계는 DOM의 비디오 요소에 스트림을 적용하는 것입니다. 비디오 요소 소스 개체를 호출하여 스트림과 동일하게 설정하기만 하면 됩니다.

이제 피어 연결을 통해 로컬 및 원격 스트림을 관리할 수 있습니다. 하지만 그렇게 하려면 파이어스토어에 신호를 좀 보내야 해요. 통화를 시작하는 사용자가 제안을 하는 사람입니다. DOM에는 해당 기능을 처리하기 위한 통화 버튼이 있습니다. 이 비동기 기능에는 두 사용자 모두의 응답과 제안을 관리하는 데 사용되는 통화 문서가 있습니다. 그런 다음 후보자에게 제안하고 해당 문서의 하위 컬렉션에 해당하는 답변을 제시합니다.

…문서를 참조할 때 각 사용자의 모든 후보가 포함됩니다. ID가 없으면 Firebase에서 자동으로 임의의 ID를 생성합니다. 먼저 UI에 입력을 채우는 데 사용합니다. UI 입력은 다른 브라우저 탭이나 세계 어딘가의 다른 사용자가 호출에 응답하는 데 사용할 수 있습니다.

이제 제안을 작성하여 데이터베이스에 저장할 준비가 되었습니다. 먼저 "동료 연결 생성 제안 방법"을 기다리면 제안 설명이 나타납니다. 그런 다음 피어 연결에 대한 로컬 설명으로 설정합니다. 가장 중요한 것은 이 개체에 SDP 값이 포함되어 있다는 것입니다. SDP 값은 Session Description Protocol(세션 설명 프로토콜)을 나타냅니다. 이것이 바로 데이터베이스에 저장하고자 하는 가치입니다. 이제 일반 JavaScript 개체로 변환한 다음 해당 데이터로 대기 호출 문서 세트를 호출하여 데이터베이스에 작성하겠습니다.

SDP 개체의 내부는 중요하지 않지만 비디오 코덱에 대한 정보와 함께 연결을 협상할 수 있는 여러 가지 정보가 포함되어 있습니다. 여기서 꼭 짚고 넘어가야 할 점은 설정 로컬 설명으로 전화를 걸자 ICE 후보가 자동으로 생성되기 시작했다는 것입니다. ICE 후보에는 실제 피어 투 피어 연결을 설정하는 데 사용할 수 있는 잠재적인 IP 주소와 포트 쌍이 포함되어 있습니다. 우리는 심장내심전도 후보자들의 말을 경청해야 하기 때문에, 전화를 걸기 전에 듣는 사람이 자리를 잡도록 하는 것이 중요합니다.

이벤트가 종료되면 후보가 존재하는지 확인한 다음, 제안 후보 모음에 데이터를 JSON으로 씁니다.

따라서, 전화를 건 사람이 제안할 때, 우리는 모든 데이터를 데이터베이스에 저장합니다. 하지만 이제는 다른 쪽에서도 사용자로부터 답변을 들어야 합니다. 이 방법은 Firestore에서 호출된 문서의 변경 내용을 듣는 것입니다. onSnapshot 메서드는 데이터베이스의 문서가 변경될 때마다 콜백을 실행합니다. 피어 연결에 현재 원격 설명이 없고 데이터에 응답이 있는 경우 로컬에서 피어 연결에 대한 답변 설명을 설정합니다. 즉, 데이터베이스에서 답변을 듣고 해당 답변이 수신되면 피어 연결에서 업데이트합니다.

그것이 초기 연결을 협상하지만 우리는 또한 응답하는 사용자로부터 ICE 후보자들의 말을 들어야 한다. 우리는 후보 답안 모음에 대한 업데이트를 들음으로써 그렇게 합니다. Firestore에는 쿼리의 문서 변경 방법을 사용하여 처리되는 컬렉션에 추가된 문서만 들을 수 있는 멋진 작은 기능이 있습니다. 따라서 새 문서를 추가할 때마다 문서 데이터를 사용하여 새 얼음 후보를 생성한 다음 피어 연결에 해당 후보를 추가할 수 있습니다. 지금은 응답 측에서 업데이트를 청취하고 있지만, 사용자가 실제로 전화를 받을 수 있는 방법을 제공해야 합니다.

전화를 받는 것은 전화를 시작하는 것과 매우 비슷합니다. 가장 큰 차이점은 Firestore에서 발신자가 작성한 것과 동일한 문서 ID의 문서를 청취한다는 것입니다. 이 문서와 답변 후보 컬렉션을 참조한 다음, 피어 커넥션에서 ICE 후보 이벤트를 청취하여 새로운 후보가 생성될 때마다 응답 후보 컬렉션을 업데이트하겠습니다.

데이터베이스에서 통화 문서를 가져와 데이터를 가져올 수 있습니다. 여기에는 피어 연결에 대한 원격 설명을 설정하는 데 사용할 수 있는 오퍼 데이터가 포함되어 있습니다.

그런 다음 로컬로 답변을 생성한 다음 로컬 설명을 답변으로 설정할 수 있습니다. 이전 기능에서와 마찬가지로 일반 객체로 설정한 다음 다른 사용자가 답변을 들을 수 있도록 통화 문서에 업데이트하겠습니다.

또한 제안 후보 컬렉션을 청취할 수 있도록 하고, 새로운 ICE 후보가 추가될 때마다 해당 지역에서 ICE 후보 제품을 만들 것입니다.

WebRTC와 함께 화상 채팅 기능을 구축하는 데 필요한 것은 이것뿐입니다. 대부분의 작업은 두 사용자 간의 데이터를 신호로 보낼 뿐입니다. WebRTC는 후드 아래의 복잡한 P2P 네트워킹 및 미디어 스트리밍을 모두 처리합니다.

이 기사가 도움이 되기를 바랍니다.

고마워요.

쉬운 영어로 더 많은 내용.이오

from http://issue-disk.tistory.com/453 by ccl(A) rewrite - 2021-07-16 05:00:50