Google은 흑인 공동체를 위한 인종적 평등을 추구하기 위해 노력하고 있습니다. 자세히 알아보기

Firebase + WebRTC Codelab

1. 소개

이 Codelab에서는 브라우저의 WebRTC API 및 신호 처리를 위한 Cloud Firestore를 사용하여 간단한 영상 채팅 애플리케이션을 빌드하는 방법을 알아봅니다. 이 애플리케이션은 FirebaseRTC라고 하며 WebRTC 사용 애플리케이션 빌드의 기본 사항을 알려주는 간단한 예시입니다.

실습 내용

  • WebRTC를 사용하여 웹 애플리케이션에서 영상 통화 시작
  • Cloud Firestore를 사용하여 원격 당사자에게 신호 전송

준비물

이 Codelab을 시작하기 전에 다음을 설치했는지 확인하세요.

  • 일반적으로 Node.js와 함께 제공되는 npm - 노드 LTS가 권장됨

2 Firebase 프로젝트 만들기 및 설정

Firebase 프로젝트 만들기

  1. Firebase Console에서 프로젝트 추가를 클릭한 후 Firebase 프로젝트의 FirebaseRTC 이름을 지정합니다.

Firebase 프로젝트의 프로젝트 ID를 기억합니다.

  1. '프로젝트 만들기'를 클릭합니다.

빌드할 애플리케이션은 웹에서 사용할 수 있는 두 가지 Firebase 서비스를 사용합니다.

  • Cloud Firestore를 사용하면 클라우드에 구조화된 데이터를 저장하고 데이터가 업데이트되면 인스턴트 알림을 받을 수 있습니다.
  • 정적 애셋을 호스팅하고 제공할 수 있는 Firebase 호스팅

이 Codelab에서는 클론할 프로젝트에 Firebase 호스팅을 이미 구성했습니다. 그러나 Cloud Firestore의 경우 Firebase Console을 사용하여 서비스를 구성하고 사용 설정하는 방법을 안내합니다.

Cloud Firestore 사용 설정

앱은 Cloud Firestore를 사용하여 채팅 메시지를 저장하고 새 채팅 메시지를 수신합니다.

Cloud Firestore를 사용 설정해야 합니다.

  1. Firebase Console 메뉴의 개발 섹션에서 데이터베이스를 클릭합니다.
  2. Cloud Firestore 창에서 데이터베이스 만들기를 클릭합니다.
  3. 테스트 모드로 시작 옵션을 선택한 다음 보안 규칙에 대한 면책조항을 읽은 후 사용을 클릭합니다.

테스트 모드를 사용하면 개발 중에 데이터베이스에 자유롭게 쓸 수 있습니다. 이 Codelab의 뒷부분에서 데이터베이스 보안을 강화하겠습니다.

3. 샘플 코드 가져오기

다음과 같이 명령줄에서 GitHub 저장소를 클론합니다.

git clone https://github.com/webrtc/FirebaseRTC

샘플 코드를 FirebaseRTC 디렉터리에 클론해야 합니다. 이제부터 이 명령줄에서 명령줄을 실행해야 합니다.

cd FirebaseRTC

시작 앱 가져오기

편집기에서 FirebaseRTC의 파일을 열고 아래 안내에 따라 변경합니다. 이 디렉터리에는 아직 작동하지 않는 WebRTC 앱으로 구성된 Codelab의 시작 코드가 포함되어 있습니다. 이 Codelab 전체에서 작동하도록 하겠습니다.

4. Firebase 명령줄 인터페이스 설치

Firebase 명령줄 인터페이스 (CLI)를 사용하면 웹 앱을 로컬에서 제공하고 웹 앱을 Firebase 호스팅에 배포할 수 있습니다.

  1. 다음 npm 명령어를 실행하여 CLI를 설치합니다. sh npm -g install firebase-tools
  1. sh firebase --version 명령어를 실행하여 CLI가 올바르게 설치되었는지 확인합니다.

Firebase CLI 버전이 v6.7.1 이상인지 확인합니다.

  1. sh firebase login 명령어를 실행하여 Firebase CLI를 승인합니다.

앱의 로컬 디렉터리와 파일에서 Firebase 호스팅에 대한 앱 구성을 가져오도록 웹 앱 템플릿을 설정했습니다. 그러나 이렇게 하려면 앱을 Firebase 프로젝트와 연결해야 합니다.

  1. sh firebase use --add 명령어를 실행하여 앱을 Firebase 프로젝트와 연결합니다.

  2. 메시지가 표시되면 프로젝트 ID를 선택한 후 Firebase 프로젝트에 별칭을 지정합니다.

별칭은 여러 환경 (프로덕션, 스테이징 등)이 있는 경우에 유용합니다. 그러나 이 Codelab에서는 default 별칭을 사용하겠습니다.

  1. 명령줄의 나머지 안내를 따릅니다.

5 로컬 서버 실행

실제로 앱에서 작업을 시작할 준비가 되었습니다. 로컬에서 앱을 실행해 보겠습니다.

  1. 다음 Firebase CLI 명령어를 실행합니다. sh firebase serve --only hosting

  2. 명령줄에 다음 응답이 표시됩니다. hosting: Local server: http://localhost:5000

Firebase 호스팅 에뮬레이터를 사용하여 앱을 로컬에서 제공하고 있습니다. 이제 웹 앱은 http://localhost:5000에서 사용할 수 있습니다.

  1. http://localhost:5000에서 앱을 엽니다.

Firebase 프로젝트에 연결된 FirebaseRTC 사본이 표시됩니다.

앱이 Firebase 프로젝트에 자동으로 연결되었습니다.

6. 새 방 만들기

이 애플리케이션에서는 각 영상 채팅 세션을 채팅방이라고 부릅니다. 사용자는 애플리케이션에서 버튼을 클릭하여 새 방을 만들 수 있습니다. 이렇게 하면 원격 당사자가 같은 방에 참여할 때 사용할 수 있는 ID가 생성됩니다. ID는 각 채팅방의 Cloud Firestore에서 키로 사용됩니다.

각 채팅방에는 오퍼와 답변에 대한 RTCSessionDescriptions와 각 당사자의 ICE 후보가 있는 개별 컬렉션 두 개가 포함됩니다.

첫 번째 작업은 호출자의 초기 혜택으로 새 방을 만드는 데 필요한 누락된 코드를 구현하는 것입니다. public/app.js를 열고 // Add code for creating a room here 주석을 찾은 후 다음 코드를 추가합니다.

const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

const roomWithOffer = {
    offer: {
        type: offer.type,
        sdp: offer.sdp
    }
}
const roomRef = await db.collection('rooms').add(roomWithOffer);
const roomId = roomRef.id;
document.querySelector('#currentRoom').innerText = `Current room is ${roomId} - You are the caller!`

첫 번째 줄은 호출자의 오퍼를 나타내는 RTCSessionDescription를 만듭니다. 그런 다음 로컬 설명으로 설정되고 마지막으로 Cloud Firestore의 새 Room 객체에 기록됩니다.

그런 다음 데이터베이스 변경사항을 수신 대기하고 피호출자의 답변이 추가된 시점을 감지합니다.

roomRef.onSnapshot(async snapshot -> {
    console.log('Got updated room:', snapshot.data());
    const data = snapshot.data();
    if (!peerConnection.currentRemoteDescription && data.answer) {
        console.log('Set remote description: ', data.answer);
        const answer = new RTCSessionDescription(data.answer)
        await peerConnection.setRemoteDescription(answer);
    }
});

이는 호출자가 답변에 대해 RTCSessionDescription를 작성할 때까지 대기한 후 호출자 RTCPeerConnection에 원격 설명으로 설정합니다.

7 채팅방에 참여 중

다음 단계는 기존 채팅방에 참여하는 로직을 구현하는 것입니다. 이렇게 하려면 채팅방 참여 버튼을 클릭하고 참여할 채팅방의 ID를 입력합니다. 여기에서 작업은 답변의 RTCSessionDescription 생성을 구현하고 이에 따라 데이터베이스의 채팅방을 업데이트합니다.

const offer = roomSnapshot.data().offer;
await peerConnection.setRemoteDescription(offer);
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);

const roomWithAnswer = {
    answer: {
        type: answer.type,
        sdp: answer.sdp
    }
}
await roomRef.update(roomWithAnswer);

위 코드에서는 먼저 호출자에서 오퍼를 추출하고 원격 설명으로 설정된 RTCSessionDescription를 만듭니다. 그런 다음 답변을 만들어 로컬 설명으로 설정하고 데이터베이스를 업데이트합니다. 데이터베이스를 업데이트하면 호출자 측에서 onSnapshot 콜백이 트리거되며 피호출자의 응답에 따라 원격 설명이 설정됩니다. 이렇게 하면 호출자와 피호출자 간의 RTCSessionDescription 객체 교환이 완료됩니다.

8 ICE 후보 수집하기

발신자와 수신자는 서로 연결할 수 있으려면 먼저 원격 피어에 연결하는 방법을 WebRTC에 알려주는 ICE 후보를 교환해야 합니다. 다음 작업은 ICE 후보를 수신 대기하고 데이터베이스의 컬렉션에 추가하는 코드를 구현하는 것입니다. collectIceCandidates 함수를 찾고 다음 코드를 추가합니다.

async function collectIceCandidates(roomRef, peerConnection,
                                    localName, remoteName) {
    const candidatesCollection = roomRef.collection(localName);

    peerConnection.addEventListener('icecandidate', event -> {
        if (event.candidate) {
            const json = event.candidate.toJSON();
            candidatesCollection.add(json);
        }
    });

    roomRef.collection(remoteName).onSnapshot(snapshot -> {
        snapshot.docChanges().forEach(change -> {
            if (change.type === "added") {
                const candidate = new RTCIceCandidate(change.doc.data());
                peerConneciton.addIceCandidate(candidate);
            }
        });
    })
}

이 함수는 두 가지 작업을 수행합니다. WebRTC API에서 ICE 후보를 수집하여 데이터베이스에 추가하고 원격 피어에서 추가된 ICE 후보를 수신 대기하고 RTCPeerConnection 인스턴스에 추가합니다. 데이터베이스 변경사항을 수신 대기할 때 새로 추가되지 않은 것을 필터링할 때 중요합니다. 그렇지 않으면 동일한 ICE 후보 집합이 계속 반복되기 때문입니다.

9. 결론

이 Codelab에서는 Cloud Firestore를 사용하여 WebRTC의 신호를 구현하는 방법과 이를 사용하여 간단한 영상 채팅 애플리케이션을 만드는 방법을 배웠습니다.

자세한 내용은 다음 리소스를 참조하세요.

  1. FirebaseRTC 소스 코드
  2. WebRTC 샘플
  3. Cloud Firestore