zoom

Steve·2023년 10월 26일
0

서버가 될 server.js생성
"@babel/cli": "^7.23.0", : 터미널에서 커맨드를 입력해서 Babel을 사용할 때 필요한 패키지
"@babel/core": "^7.23.2", : 바벨의 핵심 파일, 바벨의 다른 모듈들이 종속성을 가진다.
"@babel/node": "^7.22.19", : 바벨의 CLI 도구 중 하나. 이전 버전의 babel-cli로부터 분리됨.
@babel/preset-env : 바벨의 preset 중 하나.
es6+ 이상의 자바스크립트를 각 브라우저/노드 환경에 맞는 코드로 변환시켜줌.

babel.config.json에

{
  "presets": ["@babel/preset-env"]
}

nodemon이 호출되면 nodemon이 nodemon.json을 살펴보고 거기있는 코드실행.

static files, 또는 유저들에게 가게 될 파일 만들기

static 작업을 하는 이유?

정적 파일 제공.

socket io

websocket 은 socketio가 실시간, 양방향, event 기반 통신을 제공하는 방법 중 하나

socket io 는 웹소켓의 부가기능이 아니다.
socket io is not a websocket implementation.

socket io는 websocket을 사용한다
하지만 웹소켓을 지원하지 않으면 다른 것을 사용한다
브라우저가 websocket을 지원 안하거나, websocket 연결에 문제가 있어도
socket io는 실시간 기능을 제공함.
socket io는 프론트와 백 사이 실시간 통신을 가능케 해주는 프레임워크 또는 라이브러리
프론트와 백 간 실시간 통신을 웹소켓을 이용해서 할수도 있음
꼭 socket io 를 사용할 필요는 없음
하지만 실시간 기능 같은 것들을 더쉽게 만드는 편리한 코드를 제공함(라이브러리라는 거지)
socket io는 탄력성있음
즉, socket io가 websocket을 이용한 연결에 실패 해도 socketio 는 다른 방법을 찾을거임.
socket io는 websocket보다 약간 더 무거움.
ws는 용량이 작음. 많은 기능이 있지 않으니까.
socket io는 너의 연결이 어떤 이유에서든지 끊어지면 재연결 시도함. (신뢰할 수 있단 뜻)

우리가 웹소켓 서버를 어떻게 만들었었지?
먼저 http서버를 만들었고,

import http from "http";
import SocketIO from "socket.io";

새로운 websocket을 만들 때 http 를 위에 쌓아올리면서 만들었음

import express from "express";
const app = express();
const httpServer = http.createServer(app);
const wsServer = SocketIO(httpServer);

socketio가 websocket의 부가기능이 아니기때문
개발자가 socket io를 서버에 설치한것처럼
client에도 socketio를 설치해야함
프론트) const socket = io();

다시 말하지만 socketio는 websocket의 부가기능이 아님
과거에는 백엔드에는 아무것도 설치할 필요가 없었음
왜냐면 브라우저가 제공하는 webscoket api를 사용하면 됐으니까.
하지만 브라우저가 주는 websocket은 socketio와 호환이 안됨
왜냐면 socketio가 더 많은 기능을 주기 때문.
그래서 socketio를 브라우저에 설치해야됨.

user가 chat에 참가하고 싶으면 room을 먼저 만들도록 하게하고싶음

socket.io를 쓰면 연결된 socket을 자동적으로 추적함.
이 라이브러리를 안쓰면 foreach로 다 잡아줘야 했음.

room

서버는 백엔드에서 function을 호출하지만 function은 프론트에서 실행된거.
socket.emit, socket.on

프론트에서 함수를 만든 것을, 백에서 실행시킨다.
socket.emit("enter_room", input.value, backendDone);

const httpServer = http.createServer(app);
// http 서버생성. express이용해서.
const wsServer = SocketIO(httpServer);
// 통상적으로 io로 변수를 둠.

wsServer.on("connection", socket => { // socket은 연결된 브라우저
  // 새로운 connection 등록할 준비됨.
  socket.on("enter_room", (roomName, done) => {
    // roomName:인자 값, done : 콜할 function
    setTimeout(() => {
      done("hello from the backend"); // 프론트에 있는 함수. 백엔드가 실행시킴. 보안문제가 생긴다.. 누군가 너의 db를 지우는 코드를 작성할 수도 있자나.
    }, 1000);
  });
});

socket io는 기본적으로 room을 제공함
ex) 채팅, 배달 기사와 너 사이의 관계

socket.io에서 모든 socket은 기본적으로 User와 서버사이에 private room이 있음.
방에 들어가기 위해 socket.join
어떤 방에 있는지 알기위해 socket.rooms

방에 참가했다는 것을 방에 있는 모든 사람에게 알려주자
입장하면 form 버튼이 사라지고 방을 보여줘야함

socket.to('others') 모두에게 메세지 보냄. others는 방 제목.

disconnection : 클라와 서버가 연결이 끊어지기 전에 마지막 굿바이 message를 보낼수있음.

video call

1 유저로부터 비디오 가져오기
2 버튼 생성, 마이크 음소거, 카메라 on/off

stream을 myFace안에 넣어줘야함
myFace.srcObject = myStream

stream의 장점 : track을 제공해줌
비디오가 하나의 트랙, 오디오가 하나의 트랙

  • 유저가 가지고 있는 카메라 목록
    getUserMedia 유저의 카메라, 오디오를 가져옴

enumerateDevices()
모든 장치를 알려줌

배열을 반환해주는데 array를 통해 video input만 선택하는게 목적
저게 바로 카메라니까.

const devices = await navigator.mediaDevices.enumerateDevices();
    const cameras = devices.filter(device => device.kind === "videoinput");

선택된 id를 가져오고 stream에서 강제로 변경
camerasSelect.addEventListener("input", handleCameraChange); // select에서 뭔가를 선택할 때 함수실행.
id를 사용하는게 비디오를 강제로 다시 시작하는 방법.

facingMode environment 후면카메라. (핸폰에서만)

webrtc - 영상,오디오,텍스트 보낼 수 있음.

실시간 커뮤니케이션

p2p가 아닌거 >>
채팅할때는 모두가 서버에 연결돼 있었고 그 서버는 모두에게 메세지를 전달하는 역할을함.
a가 메세지를 보내면 서버로 보내지고, 그 서버에서 b로 전달됨
이건 p2p가 아님.

그에 반해! p2p는 내영상, 오디오가 서버로 안감. 직접 유저에게 감
web socket을 쓸때랑 다름. web socket은 이런식 (나 -> 서버 -> 너)
web rtc 서버가 필요하긴 한데 영상,오디오를 전달하기 위함은 아님
시그널링을 위해 서버임.
아래오 같은 것을 상호간 알기위한 서버임
너의 ip주소가 뭔지? 어떤 ip주소가 public인지?
내가 쓸 수 있는 port는 어떤건지?
서버 : 이처럼 상대가 어디에 있는지 알게해주는 역할을 함
시그널링이 끝나면 p2p 연결이 된거임.

내 브라우저가 서버에게 말함
내가 있는 곳은 여기, 이게 내 ip고, 내 오픈 port는 이거.
내 서버 구성은 이런 형태~
이처럼 브라우저는 서버한테 브라우저 위치, configuration만 전달.

정리 : 서로의 위치만 확인하기위해 서버를 사용하는것

방화벽이나 라우터가 있는지 등의 정보를 서버에게 전달.
socket.io,
시그널링을 위해, 위치 정보를 보내기 위해 websocket사용.
webRTC로 보낼 수 있는 정보는 뭐다?

영상, 오디오, 텍스트

room

비디오 콜 하라면 room이 필요.
getUserMedia() 로 오디오, 비디오 가져옴
addStream(). 이거 하기 전에 양쪽 브라우저에서 RTC연결을 만들어야함
서버를 사용해서 즉, socket.io를 이용해서 이어준다.

영상과 오디오 데이터를 주고 받을 때,
영상, 오디오 데이터를 peer connection에 넣어야함.
addTrack : 다른 유저에게 전송될 트랙들의 묶음에 신규 미디어 트랙을 추가.

a에서 b연결
// offer 우리가 누구이고, 어디있고 설명
이 offer로 연결을 구성함.

// 누가 우리방에 들어왔을 때

socket.on("welcome", async () => {
  const offer = await myPeerConnection.createOffer();
  console.log(offer);
  console.log("someone joined!"); // B가 들어오면 A 브라우저에서 실행되는 코드
});

영상,오디오 전달 위해 서버가 필요한게 아니라 offer를 주고받기위해 서버 필요

setRemoteDescription

peer a에서 offer를 만들었고, 그 다음 setLocalDescription을함.
peer A한테 이 description을 알려줬다는걸 의미함

보낸 offer를 b에서 받는데, RemoteDescription이 그일을 함
멀리 떨어진 peer의 description을 세팅을 한드는 것을 뜻함

a 브라우저가 offer를 만들고 전송을 할거고 b브라우저가 그 offer를 받아서 remoteDescription을 설정함.

websocket의 속도가 미디어를 가져오는 속도나 연결을 만드는 속도보다 더 빠름

getMedia하고, makeConnection 한 다음에 emit.

peer a 가 offer를 만들고 peer b가 answer를 생성.
a가 b에게 offer를 보낸것처럼
b가 a로 보낼 answer가 있을 떄 answer로 응답.

a 브라우저에서 우리는 setLocalDescription을 했고, offer를 만들었고, 그걸 b 브라우저로 보냄
b 브라우저에서 setRemoteDescription을 할거임
그 담 b 브라우저에서 answer를 만들어서 a 브라우저에게 보냄
그래서 그 answer로 a브라우저는 remoteDescription을 갖게됨.

setlocal , setRemote 각각 2개씩 있음

iceCandidate

우리가 offer, answer 받는 걸 모두 끝냈을 때,
p2p 연결의 양쪽에서 icecandidate라는 이벤트를 실행하기 시작
internet connectivity establishment(인터넷 연결생성)
이건 webRTC에 필요한 프로토콜을 의미
멀리 떨어진 장치와 소통할 수 있게 하기 위함
브라우저가 서로 소통할 수 있도록 일종의 방법.(중재 프로세스)
다수의 candidate(후보)들이 각각의연결에서 제안되고 그들은 서로의 동의하에 하나를 선택. 그것을 소통방식에 사용.

이 절차는 answer와 다른 모든 것들을 얻고 난 뒤에 발생

시작
icecandidate event를 listen

STUN server가 필요함

이 candidate들을 다른 브라우저로 보냄.
candidate들은 브라우저에의해 만들어짐

candidate은 브라우저가 ' 헤이, ㅇ이게 우리가 소통하는 방법이야' 라고 알려주는 방식

a브라우저에서 만든 candidate들을 전부 b 브라우저로 보내야함
반대로도 마찬가지.

srcObject란..?
흠..

remote stream. peer stream. 동일하게 명명.

stun server를 통해 핸드폰에서도 동작시켜보자

npm i localtunnel -> 서버를 전세계와 공유하게 해줌

문제가 뭐냐면, 내컴퓨터랑 폰이 같은 wifi에 있지 않으면 에러 발생.
stun server : 컴퓨터가 공용 ip주소를 찾게 해줌.
서로를 찾아야만함.
stun server가 필요한 이유

stun server는 어떤것을 req하면 인터넷에서 내가 누군지를 알려주는 서버
서버는 나의 공용ip를 알려줄거임.
내 겔럭시는 내컴퓨터를 찾아야하고,
내 컴퓨터는 겔럭시를 찾아야함

전문적인 사업성의 일을 하려면 본인 소유의 stun서버가 필요할거지만
지금은 구글에서 제공하는 걸사용.아래와 같음

iceServers:
WebRTC에서 ICE 프레임워크를 사용하여 피어간의 연결을 수립할 때 필요한 서버의 정보를 지정하는 역할.

ice프레임워크:
네트워크 주소 변환(NAT)과 방화벽을 통과하여 피어 간의 직접적인 통신을 가능케 하는 기술.
피어간의 통신을 위해서는 각 피어가 "서로의 주소"를 알고 있어야 하는데, 이를 위해 STUN서버가 사용됩니다.

STUN 서버:
피어의 공인 IP주소와 포트를 알려주는 역할.
따라서 iceServers에 STUN 서버의 주소를 지정하는 것은 피어가 상대 피어의 주소를 알 수 있도록 도와주는 것입니다.
만약 iceServers를 지정하지 않고 RTCPeerConnection을 생성한다면, 기본적으로 브라우저에서 제공하는 STUN서버를 사용함. 하지만 네트워크 환경에 따라 기본STUN서버가 제대로 동작하지 않을 수도 있으므로, 필요한 경우 직접 STUN서버의 주소를 지정하여 사용하는 것이 좋습니다.
따라서, iceServers를 지정하지 않고 동작은 되지만, 네트워크 상태에 따라 호환성문제가 발생할 수 있으므로, iceServers를 명시적으로 설정하는 것이 좋습니다.

const myPeerConnection = new RTCPeerConnection({
    iceServers: [
      {
        urls: [
          "stun:stun.l.google.com:19302",
          "stun:stun1.l.google.com:19302",
          "stun:stun2.l.google.com:19302",
          "stun:stun3.l.google.com:19302",
          "stun:stun4.l.google.com:19302"
        ]
      }
    ]
  }); // 이 연결을 모든 곳에 다 공유하려면?

장치는 공용주소를 알아야함
그래야 다른 네트워크에 있는 장치들이 서로를 찾을 수 있음

다시말함! 비디오,오디오를 주고받기 위해 stun서버가 필요한게 아님
!! 공용 주소를 알아내기 위해 STUN서버를 사용하고 있는것임.

시그널링 메커니즘은 webrtc에 없기때문에 알아서 짜줘야한다.
(socketio를 이용해서)
webRTC는 미디어 데이터 교환 요청만한다. offer와 answer로. SDP 포맷으로 소통한다
RTCPeerConnection API of WebRTC is used to stream audio and video between users

srcObject = stream


Room notification
누군가가 나갔을 때.
disconnecting이랑 disconnect는 다르다
disconnect는 연결이 완전 끊기는거.
disconnecting : 고객이 접속을 중단할 것이지만 아직 방을 나가지는 않음
완전히 끊기기전에 (ex.창을 닫거나 컴터가 꺼졌을 때) 방에 메세지 보낼수 있음.
socket.io덕분에 disconnecting이란걸 쓸 수가 있음
클라와 서버가 연결이 끊어지기 전에 마지막 굿바이 메세지를 보낼 수 있음
socket.rooms로 중복되는 요소가 없는 array인 Set을 받을 수 있음
그래서 forEach를 쓸 수 있지.

function handleMessageSubmit(event) {
event.preventDefault();
const input = room.querySelector("input");
const value = input.value;
socket.emit("new_message", input.value, roomName, () => {
// roomName:방이름( 이렇게 총 인자가 4개가 되버림. 그래도 괜찮음. 몇개가 와도 상관없음)
// 인자가 여러개 올 수 있음.
console.log("emit new_message안의 콘솔");

addMessage(`You : ${value}`); // value라고 안하고 그냥 input.value라고 해주면 아래 코드에 의해 빈칸으로 나오게됨

}); // 백엔드에 이벤트를 발생시킴. 백엔드에 메세지를 보내고, 3번째 인자는 백엔드에서 시작시킬 function.
input.value = "";
console.log("맨 밑줄의 콘솔"); // 이거부터 찍히네. 그래서 위에 input.value라고 하면 빈칸으로 나옴.
}

room count

방이 몇개인지, 서버에 방이 뭐뭐 몇개 있는지 확인해보기
Adapter
: 다른 서버들 사이에 실시간 앱을 동기화시킴
우리는 현재 서버의 메모리에서 Adapter를 사용하는 중
데이터베이스에는 아무것도 저장하고 있지 않음
우리가 서버를 종료하고 다시 시작할 때 모든 room과 message와 socket은 사라짐.
우린 백엔드에 db를 가져보고 싶음
앱 안에 많은 클라이언트가 있을 때 모두가 connection을 해보면 어떨까?
A브라우저와 B브라우저를 우리 서버에 연결했던것처럼.
연결이 실시간으로 서버에 있어야함
그렇기 때문에 너의 서버는 이 connection을 오픈된 상태로 유지시켜야함
한 서버에 많은 connection이 들어옴.
서버는 그 많은 커넥션을 메모리에 저장할거임
우리는 서버 메모리에서 Adapter를 사용하고 있는 중임.
우리가 만드는 2개, 3개의 서버는 같은 메모리 풀을 공유하지 않을거임.

그래서 Adapter란, 몽고DB를 사용해서 서버간 통신을 시켜주는것.

두 서버는 각각 다른 메모리가 있음. Adapter가 없으면 A서버에서 B서버로 슬랙보내는게 불가.
"모든 클라이언트가 동일한 서버에 연결되는건 아냐"
서버 A에서 슬랙을 보내면
A서버에서 Adapter와 DB를 거쳐 다시 Adapter로 가서 도착하게됨
즉, Adapter가 어플리케이션으로 통하는 창문.
어뎁터는 누가 연결됐는지, 현재 앱에 room이 얼마나 있는지 알려줌

const httpServer = http.createServer(app);
// http 서버생성. express이용해서.
const wsServer = SocketIO(httpServer); // 통상적으로 io로 변수를 둠.
wsServer.sockets.adapter를 통해서 모든 rooms를 볼 수 있음

socket은 private room이 있어서 private message를 보낼 수 있음

socket의 id를 뜻하는 sids를 가져와서 방들을 보고 이 방들이 어떤 socket을 위해서 만들어졌는지 확인. private 메세지와, 모든 사람들과 채팅하기 위한 방 구분 가능해짐.

rooms를 보면 private room과 public room이 있음
Map에 있는 모든 rooms를 확인하고 room의 id도 확인.
만약 room id를 socket id에서 찾을 수 있다면 우리가 private용 room을 찾은거임.
rood id를 socket id에서 찾을 수 없다는 우리는 public room을 찾은거임.
자 Map 데이터 구조를 보자.
const food = new map();
food.set('key', 111);
Map(1) {'key' => 111}
food.get("key")

우리에겐 sids가 있는데 그건 우리 백엔드에 연결된 모든 sockets들의 map.그리고 rooms도 있음.
때론 socket id와 room id가 동일
rooms를 정리해볼까? public room의 id만 가질 수 있도록.
모든 socket은 private room이 있다는걸 명심해! 그건 바로 id가 방제목인 경우.그래서 우리가 private message를 보낼 수 있음.
어떻게 하면 map을 반복하거나 살펴볼 수 있는지 배워봅시다
get과 key를 이용해서 key가 socket id인지, 방제목인지 알 수 있음.

adapter우리는 rooms와 sids를 확인할 수 있다.
room의 key와 함께 socket id를 가질 수 있다면 private room이라는 소리

const publichRooms = [];
  rooms.forEach((_, key) => {
    if (sids.get(kye) === undefined) {
      publichRooms.push(key);
    }
  });
 const {
    sockets: {
      adapter: { sids, rooms }
    }
  } = wsServer; // 아래 2줄과 동일.
  // const sids = wsServer.sockets.adapter.sids;
  // const rooms = wsServer.sockets.adapter.rooms;

새로운 방이 만들어졌다고 모두에게 알림.
server.sockets.emit을 이용.
클라이언트와의 연결이 종료되었을 떄도>>
클라가 종료메세지를 모두에게 보낸 다음, 우리는 모두에게 room이 변경됐다고 알릴거임
방이 아직 존재하는 이유 : disconnecting event에 있기 때문

한개의 브라우저는 한개의 서버로 커넥션을 열어줌
한개의 서버는 여러개의 브라우저로 커넥션을 여러줌
big app은 서버가 여러개 필요함.
그 서버간의 커넥션을 위해 Adapter를 사용함.
모든 클라가 동일 서버에 연결되는건 아님.

Adapter는 누가 연결됐는지, 현재 앱에 room이 얼마나 있는지 알려줌

adapter가 메모리에 있지만 나중에 몽고db나 다른거에 넣어줄거임

room id를 socket id에서 찾을 수 있다면 우리가 private room을 찾은거임.
room id를 socket id에서 못찾으면 public room임.
sids: Map(2) {
'-V1DIkd50k2fnha-AAAB' => Set(1) { '-V1DIkd50k2fnha-AAAB' },
'n0QIdDG89OAlWhoWAAAH' => Set(1) { 'n0QIdDG89OAlWhoWAAAH' }
},
이 sids는 우리 백엔드에 연결된 모든 sockets들의 map

rooms: Map(2) {
'-V1DIkd50k2fnha-AAAB' => Set(1) { '-V1DIkd50k2fnha-AAAB' },
'n0QIdDG89OAlWhoWAAAH' => Set(1) { 'n0QIdDG89OAlWhoWAAAH' }
},
rooms도 있음

모든 socekt은 private room이 있다는걸 명심

모두에게 새로운 방이 만들어졌다고 알리기

socket to emit이 아니라 sockets.emit 이용
연결된 모든 socket에게 메세지 할수있음

방 안에 있는 사람들의 수를 세보자

// 몇 명있는지 세주는 함수
function countRoom(roomName) {
return wsServer.sockets.adapter.rooms.get(roomName)?.size; // 가끔 Set일 때도, 아닐 때도 있어서 '?'로 표시
}

// 백엔드 코드
socket.on("enter_room", (roomName, done) => {
// 브라우저 2개를 키면 이 enter_room은 2번 실행됨.
// 1번쨰 인자는 값, 2번째는 우리가 콜할 function
console.log("socket.rooms >> ", socket.rooms);
socket.join(roomName);
done(); // 프론트에 있는 showRoom() 실행.
socket.to(roomName).emit("welcome", socket.nickname, countRoom(roomName)); // welcome event를 roomName에 있는 모든 사람에게 emit함.
// socket.to 이 기능 자체가 나 제외하고 다른 브라우저에게 말하라는거임.
// 윗줄 아랫줄 차이. 위는 특정 방에 있는 자에게 메세지, 아래는 모든 socket에 메세지 보냄.
wsServer.sockets.emit("room_change", publichRooms()); // 우리 서버안에 있는 모든 방의 array를 줌.
// setTimeout(() => {
// done("hello from the backend"); // 프론트에 있는 함수. 백엔드가 실행시킴. 보안문제가 생긴다.. 누군가 너의 db를 지우는 코드를 작성할 수도 있자나.
// }, 1000);
socket.on("disconnecting", () => {
// disconnecting : 방을 떠나기 바로 직전에 발생
socket.rooms.forEach(
room =>
socket.to(room).emit("bye", socket.nickname, countRoom(roomName) - 1) // 위 welcome과 bye event를 보낼 때 소켓 닉네임을 우리에게 줌.
// 퇴장하기 직전에도 countRoom, 그래서 -1 해줘야함. 나까지 계산되면 안되니까.
);
});
socket.on("disconnect", () => {
wsServer.sockets.emit("room_change", publichRooms());
});

socket.on("new_message", (msg, room, done) => {
  // 인자를 추가 구성해줌으로써 어떤 방(room)으로 메세지를 보낼것인가에 대한 해결이 됨
  socket.to(room).emit("new_message", `${socket.nickname} : ${msg}`); // 윗줄과 아랫줄 이벤트명이 같아도 된다 , socket에 새로 넣어준 nickname이기에 socket.nickname 사용가능
  done(); // 벡엔드에서 실행하지 않아. 이걸 호출했을때 프론트에서 코드를 실행함.
});
socket.on("nickname", nickname => (socket["nickname"] = nickname));

});

//프론트코드

socket.on("welcome", (user, newCount) => {
const h3 = room.querySelector("h3");
h3.innerText = Room ${roomName} (${newCount});
addMessage(${user} arrived!);
});

socket.on("bye", (left, newCount) => {
const h3 = room.querySelector("h3");
h3.innerText = Room ${roomName} (${newCount});
addMessage(${left}.. come back..);
});

socket.io에 의해 javascript 로 변환될거임.

wsServer.sockets.emit("~~~ : >> 이걸 broadcast라함. 방송하는거지
서버로부터 모든 소켓에 보내는거임.

zoom 시작

멋진점
track을 가질 수 있는거임
비디오가 하나의 트랙이 될수있고
오디오가 하나의 트랙이 될수있음
자막 트랙도. ㅇㅇ

getUserMedia()
enumerateDevices() -> 우리에게 모든 장치와 미디어 장치를 알려줌.
컴퓨터에 연결되거나, 모바일이 가지고 있는 장치 등.
kind videoinput만 가져온다 >> 그게 카메라

append VS appendchild
append는 노드 객체와 문자열 모두 추가할 수 있는 반면, appendChild는 노드 객체만 추가 가능하다.
append는 한번에 여러개의 자식 노드를 추가할 수 있지만, appendChild는 한번에 한 개만 가능하다.
append는 return값이 존재하지 않지만, appendChild는 return값이 존재한다.
내 생각엔 기능이나 확장성 면에서 append 메소드가 더 뛰어난 점이 많은 것 같다.

연결

양쪽 브라우저에서 연결통로를 만드는걸 먼저 시작
offer, answer 핑퐁핑퐁
1. a에서 setLocal하고
b로 보냄.
2. b에서 a의 description Remote 세팅하고 answer를 만듬. 그걸 또 local 세팅하고 a로 보냄
3. a에서 받고 그걸 remote 세팅함

p2p 연결의 양쪽에서 icecandidate라는 이벤트를 실행 시작.
ice candidatesms webRTC에 필요한 프로토콜 멀리떨어진 장치와 소통하게해줌. 브라우저가 서로 소통할수있게 해주느 방법.
candidate(후보)들이 각각의 연결에서 제안되고 서로의 동의하에 하나를 선택한다. 이 모든건 offer, answer를 얻고 난 뒤에 시작.

npm i localtunnel
이거로 핸드폰에서도 작동하게 해준다
lt --port 3000 이거로 url을 만들어준다

wifi가 같지 않으면 동작을 안하는데 해결책은
STUN Server

컴퓨터가 공용IP주소를 찾게해줌

p2p 연결을 하고 있기 때문에 서로를 찾아야만 함
STUN 서버는 어떤것을 request하면 인터넷에서 너가 누군지를 알려주는 서버.
서버는 너의 공용 IP를 알려줄거임.
내 컴퓨터는 내 폰을 찾아야하고,
내 폰은 컴퓨터를 찾아야함.

구글이 무료로 제공하는 서버를 사용할거임
(실제 서비스를 돌릴거면 나의 소유의 STUN서버를 운영해야함)
STUN 서버 : 너의 장치에 공용주소를 알려주는 서버

1대1로는 좋지만 다수가 같이 화상회의 할때는 좋지않다
SFU (Selectiv Forwarding Unit) 서버에 의존하는데 이거 좋음
내 스트림을 한 번만 업로드하면됨(mesh signaling 방식은 3명 있으면 3명꺼 다 올려줘야함), 여전히 3명꺼 3개를 다운로드 해야하긴함.
이 방식은 저사양의 스트림을 제공함.스크린을 공유하고 있거나 발표하고 있는 사람의 화면이라면 서버는 좀더 좋은 사양으로 제공하긴함.
사람이 업로드하는 그 똑같은 스트림을 다운로드하진 않음.
시청자는 저사양을의 스트림을 다운로드함.
Data channel이 뭔지 알아보시길.

SFU방식으로 할거임 (M 거시기 말고)
미디어 서버를 이용할거임.

profile
Front-Dev

0개의 댓글