당신은 주제를 찾고 있습니까 “웹 rtc – WebRTC? WebSockets? 5분 개념정리!“? 다음 카테고리의 웹사이트 ppa.maxfit.vn 에서 귀하의 모든 질문에 답변해 드립니다: https://ppa.maxfit.vn/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 노마드 코더 Nomad Coders 이(가) 작성한 기사에는 조회수 47,250회 및 좋아요 1,871개 개의 좋아요가 있습니다.
웹 rtc 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 WebRTC? WebSockets? 5분 개념정리! – 웹 rtc 주제에 대한 세부정보를 참조하세요
많이 들어는 봤는데……흐음…!!
WebRTC. WebSockets 개념 싹~~ 정리해드림!
–
📌 니콜라스와 WebRTC 무료로 배우기!
https://nomadcoders.co/noom
–
📌 니콜라스와 자바스크립트 무료로 배우기!
https://nomadcoders.co/javascript-for-beginners
웹 rtc 주제에 대한 자세한 내용은 여기를 참조하세요.
[기술토픽] 웹RTC – 네이버 블로그
웹RTC, Web RealTime Communication. 1. 웹RTC의 정의 및 특징. 1) 정의: 웹브라우저만으로 구현하는 실시간 고품질 커뮤니케이션 기술로, 영상, …
Source: m.blog.naver.com
Date Published: 7/20/2022
View: 8044
WebRTC
An open framework for the web that enables Real-Time Communications (RTC) capabilities in the browser.
Source: webrtc.org
Date Published: 7/1/2022
View: 8713
[webRTC] 웹RTC 예제로 화상 채팅 구현하기. – 안농이
RTC는 Real-Time Communications의 약자이다. 웹을 통해 웹어플리케이션이 비디오, 오디오 스트림 뿐만아니라 데이터를 중간의 서버가 없.
Source: dksshddl.tistory.com
Date Published: 4/23/2021
View: 5581
[WebRTC] 웹브라우저로 화상 채팅을 만들 수 있다고? – velog
그때 Web RTC 모듈을 이용해서 플랫폼을 제작했었는데,내부 구성 원리를 모른채 구현하니 뭔가 찝찝합이 남게 됐다. 그래서 이참에 WEB RTC API를 직접 …
Source: velog.io
Date Published: 2/5/2022
View: 813
WebRTC 응용 서비스를 개발하는 2가지 방법
WebRTC는 서버를 최대한 거치지 않고 P2P(Peer-to-Peer Network)로 브라우저나 단말 간에 데이터를 주고받는 기술의 웹 표준입니다.
Source: tech.kakaoenterprise.com
Date Published: 2/18/2021
View: 5711
‘CMAF vs. 웹RTC’ 초고속 동영상 서비스 기술 경쟁 – 지디넷코리아
웹RTC는 1초 미만 초저지연시간을 구현하는 가장 유망한 기술로 꼽힌다. 문제는 웹RTC를 동영상 스트리밍에 활용하려면 별도의 네트워크 인프라를 구축 …
Source: zdnet.co.kr
Date Published: 11/30/2022
View: 6947
WebRTC는 어떻게 실시간으로 데이터를 교환할 수 있을까?
WebRTC(Web Real-Time Communication) 은 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 포착하고 마음대로 스트림 할 …
Source: wormwlrm.github.io
Date Published: 1/14/2021
View: 4259
[WebRTC] WebRTC란?. 제가 회사에서 열심히 공부하면서 개발 …
WebRTC(Web Real-Time Communications)란, 웹 어플리케이션(최근에는 Andro 및 IOS도 지원) 및 사이트들이 별도의 소프트웨어 없이 음성, …
Source: medium.com
Date Published: 6/28/2021
View: 1426
WebRTC – 위키백과, 우리 모두의 백과사전
WebRTC(Web Real-Time Communication)는 웹 브라우저 간에 플러그인의 도움 없이 서로 통신할 수 있도록 설계된 API이다. W3C에서 제시된 초안이며, 음성 통화, …
Source: ko.wikipedia.org
Date Published: 11/11/2022
View: 7254
웹RTC 6년,어제와 오늘 그리고 미래 (1) – 데이터온에어
웹RTC 6년,어제와 오늘 그리고 미래 (1) 웹RTC(WebRTC, Web Real Time Communication), 플러 그인이나 설치 없이 브라우저만으로 실시간 화상통화와 데이 터 통신을 할 …
Source: dataonair.or.kr
Date Published: 2/10/2021
View: 4608
주제와 관련된 이미지 웹 rtc
주제와 관련된 더 많은 사진을 참조하십시오 WebRTC? WebSockets? 5분 개념정리!. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 웹 rtc
- Author: 노마드 코더 Nomad Coders
- Views: 조회수 47,250회
- Likes: 좋아요 1,871개
- Date Published: 2021. 9. 9.
- Video Url link: https://www.youtube.com/watch?v=5EhsjtBE7I4
[기술토픽] 웹RTC
웹RTC, Web RealTime Communication
1. 웹RTC의 정의 및 특징
1) 정의: 웹브라우저만으로 구현하는 실시간 고품질 커뮤니케이션 기술로, 영상, 음성 및 데이터 통신의 공개된 표준
2) 특징: 플러그인없이 다양한 웹브라우저간 실시간 데이터 통신을 지원
3) 구글의 웹RTC 개발 미션
“To enable rich, high-quality RTC applications to be developed for
1) the browser, 2) mobile platforms, and 3) IoT devices, and 4) allow them all
to communicate via a common set of protocols.”
브라우저, 모바일, IoT장치 그리고 모두가 공통 프로토콜 세트를 통해 통신할 수 있도록
품부한 고품질 의 RTC 어플리케이션의 개발
2. 구조
1) WEB RTC 기본구조
– 아키텍처:http://www.comworld.co.kr/news/articleView.html?idxno=49320
– 그림: http://www.hellonms.net/upload/image/2016/08/29/16/33/21718_18.PNG
– Signaling으로 APP간 3가지 정보를 교환
. Session Control message : App간의 적절한 통신 초기화, 종료, 에러 리포트
. Network Configuration : IP Address, Port 교환
. Media Capabilities : 웹 브라우저간 사용가능한 코덱 및 해상도 전송
– Signaling후, P2P 웹브라우저간 Media 통신 진행
3. 장단점
1) 단점
– 지원하는 브라우저의 한계 : 구글 주도하에 크롬만 지원했으나, 최근 몇년사이에 MS Edge, 애플 오페라, 파이어폭스가 참여하고 있어 브라우저 제약은 현저히 줄어들고 있음
– 방화벽 문제 : UDP차단하는 방화벽 우회 방법 필요. STUN/TURN서버 추가 구축으로 타 네트워크간 통신과 TCP지원기술을 추가하여 방화벽 차단 문제를 해소하는 상용 서비스가 출시중
– Signaling : Google API에는 Signaling 미포함되어, 직접 개발 구현 필요
– Scalability : 화상회의시 최대 10명(구글기준), 7명초과시 화면 깨짐 현상 사례 발생. 다자간 화상회의 구현시 MCU 활용한 구현 사례 등장
2) 장점
– 지연없는 빠른 통신 기술
– 플러그인이 없어서 추가적 개발 비용 절감.
– 무료 코덱 사용으로 비용절감
– P2P 형태의 기기간 Direct통신시 별도의 서버 기술이 불필요
– 다수의 웹컨퍼런싱 기술 무료 제공
4. 실시간 스트리밍의 기술 동향
1) 지연시간 단축 기술
– RTMP(Real Time Messaging Protocol)이 기존 프로토콜 중 가장 지연시간이 낮다고 평가지만,
콘텐츠 다운로드가 가능하여 보안성 취약한 단점이 존재
– 청크드 스트리밍 (Chunked Streaming) (콘텐츠를 잘게 쪼개 전송하는 기법) 방식으로 파일사이즈를 줄여 전송 지연시간 단축하고,
첫번째 청크가 준비될때까지의 지연 발생은 있으나, 영상의 중간지점부터 시청할 때도 빠른 응답 가능, 다운로드 방지 가능
2) 모바일 스트리밍 이용 대세
– 공중파 대비 인터넷 방송의 시간지연은 기술적 한계, 소프트웨어적 처리 필수
– 이동성, 실시간 수요 폭증
– TV, PC, 모바일 등 멀티 디바이스환경, 동일한 고품질 요구, TV 대비 PC 및 모바일의 영상 시차 최소화 요구
5. 시장동향
1) 단방향송출방송에서 양방향, 실시간, 소통형으로 변화
– 아프리카TV, 유튜브, 트위치 등 참여형 스트리밍 서비스를 선호
2) 개인방송의 속도 경쟁
– 1초라도 빨리 사용자의 적극적인 몰입을 얻어야 더 많은 기회와 수익으로 연결되는 경향
3) 다양한 모바일기기, 빠르고 안정적인 양방향 서비스 요구
– 별도 애플리케이션 개발없이, 브라우저에서 동영상 시청 및 다양한 인터렉티브 추가 가능한 웹RTC에 관심 증가
4) 웹RTC 발전
– 2010년 구글이, 온투테크놀로지(비디오압축기술업체)와 글로벌IP솔루션(스카이프 경쟁사) 인수로 웹RTC연구 본격화
– 2011년 구글웹RTC표준제안
– 2013-2014년 웹RTC 지원 브라우저 참여 활발. 이후 크롬, 파이어폭스, 오페라, 안드로이드용 크롬과 파이어폭스
– 2015년 AV1, only HTTPS 시작
– 2016년 MS와 구글의 웹RTC표준화 통합 합의로 MS 엣지 브라우저도 참여
– webrtc.org 등 활발한 웹RTC오픈소스 프로젝트 활동으로 기술 및 보안 수준 업그레이드 추세
-2017년 애플 사파리11의 웹RTC 지원
– HTTPS 지원으로 보안 강화
– UDP, TCP 자동전환하여 방화벽 차단에 대비
– 별도의 브라우저 플러그인 없이 실시간 스트리밍 지원, 비용 강점으로 작용
5) 다양한 웹RTC 활용 사례 증가
– 원격고객지원, 화상통화, 회상회의 데이터 전송, MultiUser게임
– 게임, 원격진료, 국제컨퍼런스 실용화, 국내 해외 방송 스트리밍 증가
– 양방향 서비스를 통해 투표, 채팅 등 대화형 서비스에 활용
– 미래 방송 플랫폼 기술의 표준으로 위상 자리 잡을 것이라는 전망
– 블록체인과의 협업도 활발
6) 솔루션 사례
(a) 라임라이트 네트웍스 리얼타임 스트리밍 (Limelight Realtime Streaming, RTS)
– 80개 글로벌 거점도시에서 RTMP를 웹RTC로 변환 지원하여 1초미만의 글로벌 스트리밍 가능
– RTMP 인제스트를 받을 때, Primary와 Backup 자동 이중화 정책 적용으로 다운타임 및 장애 예방
– 라임라이트의 SDK 제공. 대화형 앱 서비스, 카메라 각도나 통계 등 개인화된 라이브 데이터 처리 지원
– 사용자의 콘텐츠 이용 패턴 분석
– 소스정보 사전협의, Geo-blocking으로 특정 IP White/Black list 처리, 일회성URL생성 등으로 보안성 강화
(b) 기타 사례
– Facebook Messenger(10억), Slack, snapchat, NHN Line, KakaoTalk,Meet, AlloDuo, Amazon Chime, Amazon MayDay, SalesForce, Google Hangout, ChromeCast, Cisco Spark 등
– 영상회의, 소셜 채팅, 데이팅, 웨비나, 교육 이러닝, 고객지원 콜센터, 원격진료, 전문가상담, 컨설팅, 협업, 방송, 고객 리서치, 화상면접, 원격카메라 등
– AR/VR(증강현실, 가상현실), IoT(사물인터넷)
(c) WOWZA streaming service : https://www.wowza.com/blog/what-is-webrtc
WebRTC
With WebRTC, you can add real-time communication capabilities to your application that works on top of an open standard. It supports video, voice, and generic data to be sent between peers, allowing developers to build powerful voice- and video-communication solutions. The technology is available on all modern browsers as well as on native clients for all major platforms. The technologies behind WebRTC are implemented as an open web standard and available as regular JavaScript APIs in all major browsers. For native clients, like Android and iOS applications, a library is available that provides the same functionality. The WebRTC project is open-source and supported by Apple, Google, Microsoft and Mozilla, amongst others. This page is maintained by the Google WebRTC team.
[webRTC] 웹RTC 예제로 화상 채팅 구현하기.
1. webRTC
RTC는 Real-Time Communications의 약자이다. 웹을 통해 웹어플리케이션이 비디오, 오디오 스트림 뿐만아니라 데이터를 중간의 서버가 없
이 직접 주고 받게할 수 있는 것이 목적이다.
webRTC의 장점은 브라우저 사이에 P2P로 연결되어 어떤 플러그인이나 써드파티 소프트웨어가 필요 없다. –> 스카이프 같은 통화 기능을 웹
에서 바로 사용가능하다!
2. 튜토리얼 채팅 구현하기
우선 나는 websocket과 nodejs 서버를 이용해서 다른 브라우저에 있는 2명의 client가 서로 채팅하기로 요청,응답해서 화상채팅하는 시나리오를 이용해서 구현하였다. 각각의 서버와 클라이언트는 다음과 같은 순서의 구현이 필요하다,
클라이언트 사이드
1. 나의 비디오 스트림 가져오기
2. RTCPeerConnection 을 이용해서 peer connection 하기
서버 사이드
1. 특정 클라이언트의 채팅 요청및 응답 이벤트 구현
——- webRTC tutorial 내의 서버측 필요 기능 ——–
다른 말로, WebRTC는 4가지 종류의 서버측 기능들이 필요합니다:
사용자 탐색과 통신.
Signaling.
NAT/firewall 탐색.
P2P 실패시의 중계서버들.
—————————————
여기서 우리는 nodejs의 socket.io를 통해 사용자 탐색과 통신(??), signalling만 구현하게 됩니다.
실제로 tutorial에서도 사용자 탐색과 통신, signalling은 webRTC에 구현되있지 않고, 개발자가 선택적으로 원하는 방식을 취하면 된다고 합니다. codelab에서도 nodejs를 사용했습니다.
** 더 구체적인 webRTC signalling 정보
https://www.html5rocks.com/ko/tutorials/webrtc/infrastructure/
클라이언트 사이드 코드
1. 나의 비디오 스트림 가져오기
비디오 스트림 가져오는 코드는 엄청 쉽다.
우선 비디오 스트림을 보여줄 공간을 html, js에 정의한다.
html 내부의 video 태그 아마.. playsinline과 autoplay 특성을 적어줘야 했던걸로 기억한다..!
var localVideo = document.getElementById(‘left_cam’);
html video 태그를 js로 가져온다.
navigator.mediaDevices.getUserMedia({ audio: false, video: true }) .then(gotStream) .catch(function (e) { alert(‘getUserMedia() error: ‘ + e.name); });
navigator.mediaDevices 에서 getUserMedia를 통해 local stream을 가져오게 된다.
이떄, audio, video 값을 true, false로 원하는 스트림을 가져올 수 있다. 스트림을 요청을 한 후, 성공하면 gotStream 함수를 호출한다.
function gotStream(stream) { console.log(‘Adding local stream.’); localStream = stream; localVideo.srcObject = stream; sendMessage(‘got user media’); if (isInitiator) { maybeStart(); } }
gotStream 함수는 전달받은 stream을 localVideo에 붙이게 된다. 그리고, isInitiator가 true이면 (isInitiator는 방을 최초로 만든사람인 경우 true가 된다.)
maybeStart 함수를 호출한다.
2. RTCPeerConnection 을 이용해서 peer connection 하기
function maybeStart() { console.log(‘>>>>>>> maybeStart() ‘, isStarted, localStream, isChannelReady); if (!isStarted && typeof localStream !== ‘undefined’ && isChannelReady) { console.log(‘>>>>>> creating peer connection’); createPeerConnection(); pc.addStream(localStream); isStarted = true; console.log(‘isInitiator’, isInitiator); if (isInitiator) { doCall(); } } }
isStart는 최초 false로 저장되있고, maybeStart 함수가 처음 실행되는 경우 true로 바뀐다.
maybeStart는 createPeerConnection 함수로 peerconnection을 만들어 주고, 나의 peerconnection에 localStream을 붙인다.
그리고 isInitiator인 경우, (방을 만들었으면) doCall 함수를 통해 같은 방에 있는 client에게 rtc 요청을 하게 됩니다.
function createPeerConnection() { try { pc = new RTCPeerConnection(pcConfig); pc.onicecandidate = handleIceCandidate; pc.onaddstream = handleRemoteStreamAdded; pc.onremovestream = handleRemoteStreamRemoved; console.log(‘Created RTCPeerConnnection’); } catch (e) { console.log(‘Failed to create PeerConnection, exception: ‘ + e.message); alert(‘Cannot create RTCPeerConnection object.’); return; } }
createPeerConnection 함수에서는 pcConfig 값으로 pc(peerconnection)을 만들어 줍니다.
그리고, pc에 icecandidate, addstream, removestrea 이벤트를 추가해 줍니다.
icecandidate는 서로 통신 채널을 확립하기 위한 방법 입니다.
onaddstream은 remote 스트림이 들어오면 발생하는 이벤트입니다.
function handleRemoteStreamAdded(event) { console.log(‘Remote stream added.’); remoteStream = event.stream; console.log(event); remoteVideo.srcObject = remoteStream; }
remoteStream이 들어오면, localVideo와 마찬가지로 remoteVideo에 remoteStream을 붙여줍니다.
***pcConfig
var pcConfig = { ‘iceServers’: [{ urls: ‘stun:stun.l.google.com:19302’ }, {urls: “turn:numb.viagenie.ca”, credential: “muazkh”, username: “[email protected]”} ]};
pcConfig에는 stun, turn 서버를 적게 되는데, 간단히 설명하면
rtc 중계가 끊어질 것을 대비한 임시 서버라고 보면 간단합니다.
https://gist.github.com/yetithefoot/7592580
위의 사이트를 통해 public turn + stun 서버의 리스트를 확인할 수 있습니다.
*********************
function doCall() { console.log(‘Sending offer to peer’); pc.createOffer(setLocalAndSendMessage, handleCreateOfferError); }
doCall 함수에서는 pc.createOffer를 통해 통신 요청을 하게 됩니다.
socket.on(‘message’, function (message) { console.log(‘Client received message:’, message); if (message === ‘got user media’) { maybeStart(); } else if (message.type === ‘offer’) { if (!isInitiator && !isStarted) { maybeStart(); } pc.setRemoteDescription(new RTCSessionDescription(message)); doAnswer(); } else if (message.type === ‘answer’ && isStarted) { pc.setRemoteDescription(new RTCSessionDescription(message)); } else if (message.type === ‘candidate’ && isStarted) { var candidate = new RTCIceCandidate({ sdpMLineIndex: message.label, candidate: message.candidate }); pc.addIceCandidate(candidate); } else if (message === ‘bye’ && isStarted) { handleRemoteHangup(); } });
다음과 같은 web socket을 통해 서로 메세지를 주고 받으면서 연결을 확립하게 됩니다.
전체 코드
var isChannelReady = false; var isInitiator = false; var isStarted = false; var localStream; var pc; var remoteStream; var remoteVideo = document.getElementById(‘right_cam’); var localVideo = document.getElementById(‘left_cam’); var pcConfig = { ‘iceServers’: [{ urls: ‘stun:stun.l.google.com:19302’ }, {urls: “turn:numb.viagenie.ca”, credential: “muazkh”, username: “[email protected]”} ]}; var sdpConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true }; localVideo.addEventListener(“loadedmetadata”, function () { console.log(‘left: gotStream with width and height:’, localVideo.videoWidth, localVideo.videoHeight); }); remoteVideo.addEventListener(“loadedmetadata”, function () { console.log(‘right: gotStream with width and height:’, remoteVideo.videoWidth, remoteVideo.videoHeight); }); remoteVideo.addEventListener(‘resize’, () => { console.log(`Remote video size changed to ${remoteVideo.videoWidth}x${remoteVideo.videoHeight}`); }); socket.on(‘connect’, function () { socket.emit(“onCollabo”, socket.id); }); socket.on(‘collabo’, function (room) { socket.emit(‘create or join’, room); console.log(‘Attempted to create or join room’, room); }); socket.on(‘created’, function (room) { console.log(‘Created room ‘ + room); isInitiator = true; }); socket.on(‘full’, function (room) { console.log(‘Room ‘ + room + ‘ is full’); }); socket.on(‘join’, function (room) { console.log(‘Another peer made a request to join room ‘ + room); console.log(‘This peer is the initiator of room ‘ + room + ‘!’); isChannelReady = true; }); socket.on(‘joined’, function (room) { console.log(‘joined: ‘ + room); isChannelReady = true; }); socket.on(‘log’, function (array) { console.log.apply(console, array); }); function sendMessage(message) { console.log(‘Client sending message: ‘, message); socket.emit(‘message’, message); } // This client receives a message socket.on(‘message’, function (message) { console.log(‘Client received message:’, message); if (message === ‘got user media’) { maybeStart(); } else if (message.type === ‘offer’) { if (!isInitiator && !isStarted) { maybeStart(); } pc.setRemoteDescription(new RTCSessionDescription(message)); doAnswer(); } else if (message.type === ‘answer’ && isStarted) { pc.setRemoteDescription(new RTCSessionDescription(message)); } else if (message.type === ‘candidate’ && isStarted) { var candidate = new RTCIceCandidate({ sdpMLineIndex: message.label, candidate: message.candidate }); pc.addIceCandidate(candidate); } else if (message === ‘bye’ && isStarted) { handleRemoteHangup(); } }); navigator.mediaDevices.getUserMedia({ audio: false, video: true }) .then(gotStream) .catch(function (e) { alert(‘getUserMedia() error: ‘ + e.name); }); function gotStream(stream) { console.log(‘Adding local stream.’); localStream = stream; localVideo.srcObject = stream; sendMessage(‘got user media’); if (isInitiator) { maybeStart(); } } var constraints = { video: true }; console.log(‘Getting user media with constraints’, constraints); if (location.hostname !== ‘localhost’) { requestTurn( “stun:stun.l.google.com:19302” ); } function maybeStart() { console.log(‘>>>>>>> maybeStart() ‘, isStarted, localStream, isChannelReady); if (!isStarted && typeof localStream !== ‘undefined’ && isChannelReady) { console.log(‘>>>>>> creating peer connection’); createPeerConnection(); pc.addStream(localStream); isStarted = true; console.log(‘isInitiator’, isInitiator); if (isInitiator) { doCall(); } } } window.onbeforeunload = function () { sendMessage(‘bye’); }; ///////////////////////////////////////////////////////// function createPeerConnection() { try { pc = new RTCPeerConnection(pcConfig); pc.onicecandidate = handleIceCandidate; pc.onaddstream = handleRemoteStreamAdded; pc.onremovestream = handleRemoteStreamRemoved; console.log(‘Created RTCPeerConnnection’); } catch (e) { console.log(‘Failed to create PeerConnection, exception: ‘ + e.message); alert(‘Cannot create RTCPeerConnection object.’); return; } } function handleIceCandidate(event) { console.log(‘icecandidate event: ‘, event); if (event.candidate) { sendMessage({ type: ‘candidate’, label: event.candidate.sdpMLineIndex, id: event.candidate.sdpMid, candidate: event.candidate.candidate }); } else { console.log(‘End of candidates.’); } } function handleCreateOfferError(event) { console.log(‘createOffer() error: ‘, event); } function doCall() { console.log(‘Sending offer to peer’); pc.createOffer(setLocalAndSendMessage, handleCreateOfferError); } function doAnswer() { console.log(‘Sending answer to peer.’); pc.createAnswer().then( setLocalAndSendMessage, onCreateSessionDescriptionError ); } function setLocalAndSendMessage(sessionDescription) { pc.setLocalDescription(sessionDescription); console.log(‘setLocalAndSendMessage sending message’, sessionDescription); sendMessage(sessionDescription); } function onCreateSessionDescriptionError(error) { trace(‘Failed to create session description: ‘ + error.toString()); } /*turn 서버 요청 CORS 문제 발생*/ function requestTurn(turnURL) { var turnExists = true; // for (var i in pcConfig.iceServers) { // if (pcConfig.iceServers[i].urls.substr(0, 5) === ‘stun:’) { // turnExists = true; // turnReady = true; // console.log(“Exist stun server”); // break; // } // } if (!turnExists) { // console.log(‘Getting TURN server from ‘, turnURL); // // No TURN server. Get one from computeengineondemand.appspot.com: // var xhr = new XMLHttpRequest(); // xhr.onreadystatechange = function() { // if (xhr.readyState === 4 && xhr.status === 200) { // var turnServer = JSON.parse(xhr.responseText); // console.log(‘Got TURN server: ‘, turnServer); // pcConfig.iceServers.push({ // ‘urls’: ‘turn:’ + turnServer.username + ‘@’ + turnServer.turn, // ‘credential’: turnServer.password // }); // turnReady = true; // } // }; // // xhr.open(‘GET’, turnURL, true); // xhr.send(); } } function handleRemoteStreamAdded(event) { console.log(‘Remote stream added.’); remoteStream = event.stream; console.log(event); remoteVideo.srcObject = remoteStream; } function handleRemoteStreamRemoved(event) { console.log(‘Remote stream removed. Event: ‘, event); } function hangup() { console.log(‘Hanging up.’); stop(); sendMessage(‘bye’); } function handleRemoteHangup() { console.log(‘Session terminated.’); stop(); isInitiator = false; } function stop() { isStarted = false; pc.close(); pc = null; }
위의 적지 않은 코드는 로그 기능과 함수이름을 통해 쉽게 알 수 있는 부분, 혹은 제가 구현하면서 이해할 필요 없을 것 같은 부분은 적지 않았습니다
서버 사이드 코드
서버 측은 각자 구현방식에 따라 달라질 것 같습니다.
socket.on(‘collabo’, function (room) { socket.emit(‘create or join’, room); console.log(‘Attempted to create or join room’, room); });
서버에서 간단하게 request, response 채널을 통해 한개의 브라우저가 임의의 room을 생성하여 request를 하면, 타겟 브라우저는 response를 하고, response가 참이라면(수락), 응답해서 설정한 임의의 room에 들어가도록 구현하였습니다.
이때 저는 response와 request를 받을 때, broadcast를 사용했지만, 실제 어플리케이션을 만들 때에는 타겟이 되는 브라우저의 socket id나 특정 값을 통해 response, request 요청을 해야할 것 같습니다.
socket.on(‘connect’, function () { socket.emit(“onCollabo”, socket.id); });
클라이언트측 onCollabo 소켓 채널 소켓이 열리면, 채널에 새로운 브라우저(화상채팅)가 열렸다고 알려주고, 서버는 이를 통해 create or join 채널을 통해 room에 들어가도록 합니다.
socket.on(‘create or join’, function (room) { log(‘Received request to create or join room ‘ + room); var clientsInRoom = io.sockets.adapter.rooms[room]; var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0; log(‘Room ‘ + room + ‘ now has ‘ + numClients + ‘ client(s)’); if (numClients === 0) { socket.join(room); log(‘Client ID ‘ + socket.id + ‘ created room ‘ + room); socket.emit(‘created’, room, socket.id); } else if (numClients === 1) { log(‘Client ID ‘ + socket.id + ‘ joined room ‘ + room); io.sockets.in(room).emit(‘join’, room); socket.join(room); socket.emit(‘joined’, room, socket.id); io.sockets.in(room).emit(‘ready’, room); socket.broadcast.emit(‘ready’, room); } else { // max two clients socket.emit(‘full’, room); } });
create or join 채널은 다음과 같이 방의 client 수(최대2명)을 조절해 주고, room 내의 client(peer)들 간의 통신이 이루어 질 수 있도록 이벤트 채널을 발생시켜 파라미터 설정을 해주게 됩니다. (isInitiator, isChannelReady 등등)
실행
nodejs 실행
node js를 실행 시켜 줍니다. 저는 webStorm을 사용 했지만 그렇지 않은경우 cmd 창에서 node app.js를 입력하면 됩니다.
카메라 권한 요청
그럼 다음과 같은 권한이 요청 됩니다. 이때 pc에 카메라(웹캠)가 없으면 try catch에 의해 오류가 발생합니다.. getMedia 어쩌구..
**** https 서버사용 ****
http 서버를 사용하게 되면 카메라 권한을 가져올 수 없어서(보안 때문에) 오류가 발생 합니다.
따라서 nodejs 서버를 만들 때 https로 만들어 주어야합니다.
그런데 https 를 만들기 위해서는 인증서가 필요합니다.
윈도우에서도 발급받을 수 있지만.. 리눅스에서 발급받는것이 훨씬 간단합니다..!
http://blog.saltfactory.net/implements-nodejs-based-https-server/
위의 링크를 통해 간단하게 nodejs 자체 https 서버를 만들 수 있습니다.
결과 1번 컴퓨터와 2번 노트북 webcam 간 화상이 가능한 것을 확인할 수 있었습니다.
후기
자바 스크립트, html을 거의 해보지 않아서 이것저것 하는데 많이 힘들었다.
특히 nodejs 만들때, 라우팅하고, 프로젝트 구조 살펴보고 npm 사용하고.. 서버 코딩에 관해서 많은 부분을 공부했다.
또 자바 스크립트의 문법을 거의 모르다 보니까 직접 구현하는게 어려워 거의 코드를 가져다 썻다.
방학 내에 자바 스크립트와 html 공부좀 해야겠따 ㅠ.ㅠ 지난번에 쟝고도 사용해본 적이 있는데 확실히 백엔드 프론트엔드 둘다 자바 스크립
트를 사용하니 훨씬 일관성..?이 있어서 편했다. 또 html 만들 떄 쟝고에서는 어떤 템플릿 엔진을 사용했던것 같은데, 이번에는 쌩 html을
이용하다보니 코드가 많이 못생겼다.. nodejs 프로젝트 path나 routing 부분에 관련에서도 좀 더 공부가 필요 했다.
다음에는 webRTC 데이터채널을 이용해서 데이터를 교환하는 웹어플리케이션을 구현해봐야겠다!
출처 및 도움
https://www.html5rocks.com/ko/tutorials/webrtc/basics/#ice
기본 튜토리얼
https://www.html5rocks.com/ko/tutorials/webrtc/infrastructure/
signalling 방법
https://github.com/muaz-khan/WebRTC-Experiment/blob/master/demos/remote-stream-recording.html
그냥 소스코드..
https://codelabs.developers.google.com/codelabs/webrtc-web/#0
webRTC codelab 정말 자세하게 설명되있다. 97퍼센트는 여기 코드를 사용했다…!
https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API
webRTC API
https://www.tutorialspoint.com/webrtc/webrtc_rtcpeerconnection_apis.htm
코드 예제
https://stackoverflow.com/questions/22233980/implementing-our-own-stun-turn-server-for-webrtc-application
turn, stun 서버 연결 stackoverflow 질문..
[WebRTC] 웹브라우저로 화상 채팅을 만들 수 있다고?
글을 적게된 이유
항상 글 시작은 비슷한 레퍼토리다. 평소에 관심이 많아서..ㅋㅋ
이전에 코딩 과외 플랫폼을 제작한 적이있다.
그때 Web RTC 모듈을 이용해서 플랫폼을 제작했었는데,내부 구성 원리를 모른채 구현하니 뭔가 찝찝합이 남게 됐다.
그래서 이참에 WEB RTC API를 직접사용하여 서버와 연결 해보자 라고 생각을 하게 됐고, 포스팅을 하게 됐다.
그런데 막상 공부를 하게 되니, 공부해야할 양은 많고, 참고할만한 레퍼런스는 많지 않거나 영어라서 시간이 오래걸렸다. (WEB RTC 튜토리얼을 분석하는데도 거의 일주일이란 시간을 다 쓴 것 같다.).
그러다 보니 아 이걸 포스팅으로 남겨 놓지 않으면 손해겠구나라고 생각해서 글을 쓰게 됐다.
WEB RTC란?
WebRTC(Web Real-Time Communications)란, 웹 어플리케이션(최근에는 android 및 ios도 지원) 및 사이트들이 별도의 소프트웨어 없이 음성, 영상 미디어 혹은 텍스트, 파일 같은 데이터를 브라우져끼리 주고 받을 수 있게 만든 기술이다. WebRTC로 구성된 프로그램들은 별도의 플러그인이나 소프트웨어 없이 p2p 화상회의 및 데이터 공유를 한다.- 출처 – 바로가기
한마디로 요약하자면, 웹 브라우저 상에서 어떤 플러그인 없이 음성채팅은 물론이며 화상채팅, 데이터 교환 까지도 가능하게하는 기술이라고 보면된다.
WEB RTC 통신 원리
Web RTC 기술은 P2P 통신에 최적화 되어있다.
Web RTC에 사용되는 기술은 여러가지가 있지만 크게 3가지의 클래스에 의해서 실시간 데이터 교환이 일어난다.
MediaStream – 카메라/마이크 등 데이터 스트림 접근
RTCPeerConnection – 암호화 및 대역폭 관리 및 오디오 또는 비디오 연결
RTCDataChannel – 일반적인 데이터 P2P통신
이 3가지의 객체를 통해서 데이터 교환이 이뤄지며 RTCPeerConnection들이 적절하게 데이터를 교환할 수 있게 처리하는 과정을 시그널링(Signaling) 이라고 한다.
위그림은 시그널링 하는 과정을 나타낸 것인데,PeerConnection은 두 명의 유저가 스트림을 주고 받는 것이므로 연결을 요청한 콜러(caller)와 연결을 받는 콜리(callee)가 존재한다. 콜러와 콜리가 통신을 하기 위해서는 중간 역할을 하는 서버가 필요하고 서버를 통해서 SessionDescription을 서로 주고 받아야 한다.
간단한 용어 정리
Web RTC API를 들여다보면 참 익숙치 않은 메소드와 용어들이 자주 등장한다.
튜토리얼글을 싸지르기(?) 앞서, 혼자 분석하면서 어렵거나 이해하기 힘들었던 용어들을 간략하게 정리해보았다.
Stun Server , Turn Server
Web RTC는 P2P에 최적화 되어있다. 즉 Peer들간의 공인 네트워크 주소(ip)를 알아 데이터 교환을 해야하는데, 실제 개개인의 컴퓨터는 방화벽등 여러가지 보호장치들이 존재하고 있다.
그래서 Peer들간의 연결이 쉽지 않은데, 이렇게 서로간의 연결을 위한 정보를 공유하여 P2P 통신을 가능하게 해주는 것이 Stun/Turn Server이다.
(https://alnova2.tistory.com/1110 에 더 자세한 내용이 담겨있다.)
SDP (Session Description Protocol)
세션 기술 프로토콜(Session Description Protocol, SDP)은 스트리밍 미디어의 초기화 인수를 기술하기 위한 포맷이다. 이 규격은 IETF의 RFC 4566로 규정되어 있다.
실제로 WEB RTC는 SDP format 에 맞춰져 영상,음성 데이터를 교환하고 있다.
Ice (Interactive Connectivity Establishment)
NAT환경에서 자신의 Public IP를 파악하고 상대방에게 데이터를 전송하기 위한 Peer간의 응답 프로토콜로 일반적으로 STUN/TURN을 이용해서 구축을 한다.
간단하게 설명하면, 한쪽이 Offer를 보내면 다른 한쪽이 Answer함으로써 피어간 연결이 설정된다
출처: https://wecomm.tistory.com/3 [미래를 여는 세상]
Web RTC를 이용하여 화상통화 구현하기
이제 화상통화와 관련된 간단한 튜토리얼을 작성할텐데, 소스코드양이 많기 때문에 주요 부분만 설명하고 넘어 갈터이니 궁금한점 있다면 댓글 쓰윽 달아주길 바랍니다
rtc.html
< html > < head > < meta charset = " utf-8 " /> < title > WebRtc tutorial title > head > < body > < div > < video id = " localVideo " autoplay width = " 480px " > video > < video id = " remoteVideo " width = " 480px " autoplay > video > div > < script src = " /socket.io/socket.io.js " > script > < script src = " ./rtc.js " > script > body > html >
화상통화를 구현하기 위해서는 내 화면과 상대방의 화면을 나타낼 뷰를 제작하여 준다.
또한 시그널링과정에 필요한 socket.io cdn또한 설정하여 준다.
rtc.js : 내 영상 정보 가져오기
let localVideo = document . getElementById ( “localVideo” ) ; let remoteVideo = document . getElementById ( “remoteVideo” ) ; let localStream ; navigator . mediaDevices . getUserMedia ( { video : true , audio : false , } ) . then ( gotStream ) . catch ( ( error ) => console . error ( error ) ) ; function gotStream ( stream ) { console . log ( “Adding local stream” ) ; localStream = stream ; localVideo . srcObject = stream ; sendMessage ( “got user media” ) ; if ( isInitiator ) { maybeStart ( ) ; } }
mediaDevice 객체의 getUserMedia Method를 통해서 사용자의 미디어 데이터를 스트림으로 받아올 수 있다. localStream과 localVideo에 출력할 영상을 본인 캠으로 지정한다.
sendMessage()
function sendMessage ( message ) { console . log ( ‘Client sending message: ‘ , message ) ; socket . emit ( ‘message’ , message ) ; }
시그널링 서버로 소켓정보를 전송하는 메소드이다. 후에 많이 언급됌. 시그널링 서버, 다른 Peer로의 데이터를 전송하는 method라고 보면 된다.
rtc.js : RTC Peer 연결하기
function createPeerConnection ( ) { try { pc = new RTCPeerConnection ( null ) ; pc . onicecandidate = handleIceCandidate ; pc . onaddstream = handleRemoteStreamAdded ; console . log ( “Created RTCPeerConnection” ) ; } catch ( e ) { alert ( “connot create RTCPeerConnection object” ) ; return ; } } function handleIceCandidate ( event ) { console . log ( “iceCandidateEvent” , event ) ; if ( event . candidate ) { sendMessage ( { type : “candidate” , label : event . candidate . sdpMLineIndex , id : event . candidate . sdpMid , candidate : event . candidate . candidate , } ) ; } else { console . log ( “end of candidates” ) ; } } function handleCreateOfferError ( event ) { console . log ( “createOffer() error: ” , event ) ; } function handleRemoteStreamAdded ( event ) { console . log ( “remote stream added” ) ; remoteStream = event . stream ; remoteVideo . srcObject = remoteStream ; }
createPeerConnection을 통해 RTCPeerConnection에 대한 객체를 형성해주고 있다.
iceCandidate는 데이터 교환을 할 대상의 EndPoint 정보라고 보면 된다.
따라서 iceCandidate할 대상이 생긴다면 handleIceCandidate Method를 실행하게 된다.
이 부분은 signaling 서버로 넘겨줘 상대방 Peer가 내 Stream을 연결할 수 있도록 한다.
연결된 Peer는 handleRemoteStreamAdded Method를 통해서 remoteVideo 뷰에 띄우도록 한다.
function maybeStart ( ) { console . log ( “>>MaybeStart() : ” , isStarted , localStream , isChannelReady ) ; if ( ! isStarted && typeof localStream !== “undefined” && isChannelReady ) { console . log ( “>>>>> creating peer connection” ) ; createPeerConnection ( ) ; pc . addStream ( localStream ) ; isStarted = true ; console . log ( “isInitiator : ” , isInitiator ) ; if ( isInitiator ) { doCall ( ) ; } } else { console . error ( ‘maybeStart not Started!’ ) ; } }
maybeStart method는 자신의 RTCPeerConnection을 초기화하고 상대방의 RTCPeerConnection과 연결하는 함수이다.
실제로 연결이 됐다면 doCall함수를 실행시켜 데이터를 주고 받는다.
function doCall ( ) { console . log ( “Sending offer to peer” ) ; pc . createOffer ( setLocalAndSendMessage , handleCreateOfferError ) ; } function doAnswer ( ) { console . log ( “Sending answer to peer” ) ; pc . createAnswer ( ) . then ( setLocalAndSendMessage , onCreateSessionDescriptionError ) ; } function setLocalAndSendMessage ( sessionDescription ) { pc . setLocalDescription ( sessionDescription ) ; sendMessage ( sessionDescription ) ; }
doCall과 doAnswer를 통해서 Description을 교환하고 이 과정을 통해서 내 화상 정보가 상대방에게, 상대방의 화상정보가 내 뷰에 출력할 수 있게 되는 것이다.
let pcConfig = { ‘iceServers’ : [ { ‘urls’ : ‘stun:stun.l.google.com:19302’ } ] } socket . on ( ‘message’ , ( message ) => { console . log ( ‘Client received message :’ , message ) ; if ( message === ‘got user media’ ) { maybeStart ( ) ; } else if ( message . type === ‘offer’ ) { if ( ! isInitiator && ! isStarted ) { maybeStart ( ) ; } pc . setRemoteDescription ( new RTCSessionDescription ( message ) ) ; doAnswer ( ) ; } else if ( message . type === ‘answer’ && isStarted ) { pc . setRemoteDescription ( new RTCSessionDescription ( message ) ) ; } else if ( message . type === ‘candidate’ && isStarted ) { const candidate = new RTCIceCandidate ( { sdpMLineIndex : message . label , candidate : message . candidate } ) ; pc . addIceCandidate ( candidate ) ; } } )
위는 소켓통신에 대한 부분을 정의해서 데이터 교환을 올바르게 할 수 있게 해준다.
const http = require ( ‘http’ ) ; const os = require ( ‘os’ ) ; const socketIO = require ( ‘socket.io’ ) ; const nodeStatic = require ( ‘node-static’ ) ; let fileServer = new ( nodeStatic . Server ) ( ) ; let app = http . createServer ( ( req , res ) => { fileServer . serve ( req , res ) ; } ) . listen ( 8080 ) ; let io = socketIO . listen ( app ) ; io . sockets . on ( ‘connection’ , socket => { function log ( ) { let array = [ ‘Message from server:’ ] ; array . push . apply ( array , arguments ) ; socket . emit ( ‘log’ , array ) ; } socket . on ( ‘message’ , message => { log ( ‘Client said : ‘ , message ) ; socket . broadcast . emit ( ‘message’ , message ) ; } ) ; socket . on ( ‘create or join’ , room => { let clientsInRoom = io . sockets . adapter . rooms [ room ] ; let numClients = clientsInRoom ? Object . keys ( clientsInRoom . sockets ) . length : 0 ; log ( ‘Room ‘ + room + ‘ now has ‘ + numClients + ‘ client(s)’ ) ; if ( numClients === 0 ) { console . log ( ‘create room!’ ) ; socket . join ( room ) ; log ( ‘Client ID ‘ + socket . id + ‘ created room ‘ + room ) ; socket . emit ( ‘created’ , room , socket . id ) ; } else if ( numClients === 1 ) { console . log ( ‘join room!’ ) ; log ( ‘Client Id’ + socket . id + ‘joined room’ + room ) ; io . sockets . in ( room ) . emit ( ‘join’ , room ) ; socket . join ( room ) ; socket . emit ( ‘joined’ , room , socket . id ) ; io . sockets . in ( room ) . emit ( ‘ready’ ) ; } else { socket . emit ( ‘full’ , room ) ; } } ) ; } ) ;
위는 signaling 서버에 대한 구현으로 room이 없다면 생성하고, room이 이미 존재한다면 room에 참가하여 내 뷰를 상대방에게 중개해주는 그런 역할을 한다.
그런다음 서버를 실행시키면,,
실시간으로 중개되는 서버를 볼수가 있다. (난 뿌듯했다.)
코드 전체 보기
코드의양이 생각보다 많기 때문에 (합쳐서 300~400줄?) , 포스팅 된 글은 참고하면서 소스를 분석하는 방법을 추천한다.
코드는 https://github.com/ehdrms2034/WebRtcTutorial 에서 본문의 소스를 볼 수 있다.
WebRTC 응용 서비스를 개발하는 2가지 방법
시작하며
코로나로 인해 마음 놓고 서로를 대면할 수 없는 시대로 살아온 지 벌써 2년이 되어갑니다. 우리 안에 공포가 자리 잡았고 그렇게 금방이라도 와르르 무너질 것 같았던 인간 사회는 이제는 그럭저럭 적응해가고 있는 듯합니다. 다행스럽게도 21세기를 살아가는 인간에게는 직접 만나지 않고도 문제를 해결할 수 있는 여러 도구를 갖고 있었기 때문입니다. 그중 하나가 바로 오늘 이야기할 WebRTC 기술인데요. 오늘 포스팅에서는 WebRTC에 대해 자세히 알아보고, WebRTC 응용 서비스를 개발할 수 있는 2가지 방법에 대해 살펴보겠습니다.
WebRTC란?
WebRTC는 서버를 최대한 거치지 않고 P2P(Peer-to-Peer Network)로 브라우저나 단말 간에 데이터를 주고받는 기술의 웹 표준입니다. 웹에서 실시간 미디어 스트림을 송수신할 수 있는 유일한 표준이고 또 유일한 P2P 표준이기도 합니다.
또한 WebRTC는 표준임과 동시에 표준을 구현한 오픈소스 프로젝트의 이름이기도 합니다. 사실 프로젝트가 먼저 있었고 표준화는 나중에 되었는데, 통신사와 통신솔루션 기업이 독점하고 있던 핵심 통신 기술을 구글이 주도해서 오픈소스화 및 표준화를 진행했습니다.
① WebRTC 역사
WebRTC 등장 이전에는 고가의 라이선스 구매 비용을 들여서 통화 기능, 화상회의 기능 등을 개발해야 했습니다. 하지만 2010년, IT 기술 중에서도 유독 라이선스 사용에 많은 비용이 드는 기술이었던 VoIP(Voice over Internet Protocol) 시장에 기존에는 상상하기 어려웠던 뉴스가 등장했습니다. 구글이 WebRTC의 근간이 되는 여러 독점 기술 기업들(On2, GIPS)을 인수해서 WebRTC 기술을 오픈소스로 풀어버린 겁니다. 이 기술들은 그전까지는 그야말로 세계 탑 수준의 미디어 엔진 및 코덱이었는데 이것을 오픈 한 뒤, 급기야 크롬 브라우저에 탑재시키고 표준화 단체까지 만듭니다. 그리고 이것을 2011년 말에 완료해버리는 놀라운 실행력을 보여줍니다. 기존 통신사와 거대 통신솔루션 기업들은 깜짝 놀라게 됩니다. 그리고 오늘날 WebRTC의 시대가 열렸습니다.
사실 오늘날의 WebRTC가 있기까지 구글의 기여는 이루 말할 수 없죠. 구글 덕분에 VoIP 서비스 이상의 다양한 혁신적인 서비스를 개발할 수 있는 세상이 열렸고 코로나19 바이러스로 인한 비대면 시대에 널리 쓰이는 기술 중 하나가 되었습니다. 구글이기에 가능했던 시도가 아니었을까 싶습니다.
② WebRTC의 특징
기술적인 관점에서 WebRTC는 상당히 독특합니다. 사실 너무 독특해서 쉽게 적용하기 어렵습니다. 하지만 이러한 독특함 덕분에 앞으로도 WebRTC 기술은 자신만의 자리를 지키며 성장할 것으로 보입니다.
WebRTC는 웹에서 사용할 수 있는 유일한 P2P 기술입니다. 때문에 각각의 클라이언트들을 연결하는 과정도 남다릅니다. 각각의 기기가 서버 도움 없이 연결되기 위해 이 연결을 도와주는 서버(Signaling)가 필요하고 P2P 연결이 불가능한 상황을 대비한 릴레이 서버(TURN)가 필요합니다.
WebRTC는 UDP(User Datagram Protocol) 기반의 스트리밍 기술입니다. HTTP/3 이전까지는 거의 유일한 UDP 기반의 웹 표준이었죠. P2P와 UDP 기반의 여러 프로토콜 덕택에 WebRTC를 이용한 스트리밍은 현존하는 기술 중 Latency가 가장 짧은 것 중 하나가 되었습니다.
이와 같은 기술적인 특징 덕분에 WebRTC는 다른 어떤 기술보다 빠르게 음성과 영상을 전송할 수 있습니다. 마치 채팅 메시지처럼 음성과 영상을 매우 즉각적인 서비스에 적용할 수 있다는 뜻입니다. WebRTC로 일확천금을 획득한 선구자들은 바로 이러한 점을 무기로 킬러 서비스를 개발해왔습니다.
WebRTC 활용 분야
WebRTC는 기본적으로 P2P 스트리밍 기술에서 출발하였지만, WebRTC 선구자들은 이 P2P의 특징을 확장해서 다양한 응용서비스를 개발해왔습니다. WebRTC를 이용한 서비스는 크게 3가지 방식으로 사용합니다. 첫 번째는 1:1 방식, 두 번째는 방송에 사용되는 1:N 방식, 세 번째는 회의형 방식인 N:N 방식입니다.
[그림 1] WebRTC로 가능한 언택트 서비스들① 1:1 방식 서비스
WebRTC가 제공하는 P2P 기능을 기반으로 하는 서비스로, 기존의 VoIP 기술이나 전화 서비스 등을 대체할 수 있습니다. 국가 공인 전화번호만 부여되지 않을 뿐, 품질이나 기능성에서는 WebRTC가 전화보다 뒤떨어질 이유가 없습니다. WebRTC는 이미 우리가 접하는 수많은 통화 앱(카카오톡 보이스톡 등)에서 사용되어 왔습니다. 또한 전화 영어나 심리 및 의료상담 등에서도 WebRTC를 활용하고 있습니다. 특히 하이퍼커넥트의 Azar는 WebRTC를 활용한 1:1 방식 서비스 중 가장 크게 성공한 서비스 중 하나입니다.
② 1:N 방송 서비스
기존 방송 기술의 지연시간은 보통 5~20초로, 3초 아래의 지연시간을 보장하기 어려운데요. WebRTC는 낮은 지연시간을 필요로 하는 생방송 서비스에서 인기를 끌고 있습니다. 특히 라이브 커머스, 라이브 옥션, 라이브 퀴즈, 웨비나, 꿀잼 퀴즈방 방송 등 시청자와 활발한 소통이 필요한 분야에서 필수 기술로 자리 잡고 있습니다.
대량 접속 환경에서 WebRTC의 P2P 성격은 버려지지만, 여전히 생방송에서 요구되는 낮은 지연 시간은 보장됩니다. Hopin과 같은 웨비나 서비스는 WebRTC를 활용한 1:N 방송 서비스 중 가장 크게 성공한 서비스입니다.
③ N:N 회의형 서비스
WebRTC를 이용한 화상회의 서비스는 COVID-19 시대에 신이 내린 선물입니다. 인간은 적절한 시기에 WebRTC를 준비하고 있었고, 이를 기반으로 하는 화상회의 서비스들은 마치 노아의 방주처럼 우리 사이에 놓인 바이러스의 강에 다리 역할을 해주었습니다.
단지 비즈니스나 교육을 위해서만 WebRTC N:N 기술이 사용되지는 않습니다. 클럽하우스 서비스처럼 왁자지껄한 원격 만남이 필요한 분야라면 WebRTC의 N:N 기술은 어디에나 존재할 수 있습니다. 우리는 이미 수많은 N:N 회의형 킬러 서비스들을 알고 있는데, 이들은 모두 WebRTC 기술을 활용하고 있습니다.
④ 2021년 WebRTC 응용 서비스 분야
WebRTC의 존재감은 연초부터 클럽하우스 서비스를 통해서 다시 한번 강력하게 드러났습니다. 클럽하우스는 화상회의 기술이 B2C(Business to Customer) 영역에서도 성공할 수 있음을 보여주는 사례였습니다. 물론 그 이전에도 스푼라디오나 하쿠나라이브와 같이 성공한 B2C 서비스들은 존재했지만 말이죠.
클럽하우스는 기술적으로 흥미로운 부분이 많습니다. N:N과 같은 화상회의형 방식에 1:N의 방송 서비스 형식을 결합했다는 점인데요. WebRTC의 장점인 다수의 스트림을 자유자재로 연결할 수 있다는 점을 잘 활용했습니다. 앞으로 이와 유사한 서비스가 계속 변화를 주면서 출시될 것으로 보입니다.
화상회의 서비스도 여전히 성장하고 있습니다. 2020년이 화상회의의 기본적인 성능 개선(동시접속자 제어, 화질 개선)에 초점을 맞추었다면 2021년에는 메타버스와 AI 같은 다른 기술과의 접목 혹은 Gather Town처럼 차별화된 UX 등으로 시장에 도전하고 있습니다.
한국의 경우 라이브 커머스 시장이 유독 성장하고 있고, 웨비나와 원격 의료 및 상담 분야의 시장도 커지고 있습니다. WebRTC 응용 서비스 시장은 한 가지 킬러 서비스만 존재하지 않습니다. 거의 매해 킬러 서비스가 바뀌어왔는데요. 초창기에는 Azar와 같은 랜덤 화상채팅 서비스가 킬러 서비스였다면 그 이후 비고라이브같은 모바일 개인방송 서비스가 현재까지도 많은 사랑을 받아왔습니다. 코로나 이후로 라이브 커머스와 화상회의 및 웨비나 서비스가 큰 호응을 얻고 있지만 클럽하우스와 같이 언제 새로운 형태의 서비스가 나타날지 알 수 없는 시장이기도 합니다. 그만큼 변화가 빠르고 도전할 영역이 많은 시장입니다.
WebRTC 기술의 어려움
그 어느 때보다도 WebRTC 기술이 절실한 시기이지만 체감적으로 WebRTC 응용 서비스가 많은 편은 아닙니다. WebRTC 기술은 다른 IT 기술에 비해 전문가가 부족하고 기술 자체도 어려워, 관련 기술 문서도 매우 부족한 편입니다. WebRTC로 서비스를 개발하다보면 다음과 같은 어려움을 겪게 됩니다.
① 네트워크 환경에 따른 품질의 불확실성
웹 환경에서 살고 있는 우리는 사실 매우 신뢰도가 높은 프로토콜인 TCP 기반의 서비스를 주로 경험하고 있기 때문에 네트워크가 얼마나 극도로 예민한 녀석인지 잊어버리곤 합니다. WebRTC는 UDP 기반의 RTP 프로토콜을 사용하고 있습니다. 품질을 보정하는 기술이 내장되어 있지만, 네트워크 기술에 대한 이해와 충분한 개발 경험이 없다면 WebRTC 기반의 서비스 개발에 성공했다고 안정적인 품질을 보장할 수 없다는 것을 곧 깨닫게 될 것입니다.
더구나 라이브 스트리밍에서 음성 영상 품질을 정량적으로 측정하는 것은 음식의 맛을 절대적 기준으로 정량화하는 것만큼이나 어려운 일입니다. 어떤 청취자는 소리가 작은 것만으로도 품질이 낮아졌다고 평가하며, 어떤 청취자는 적당한 에코에도 품질이 좋다고 생각합니다.
또한 모빌리티 환경의 품질은 갈수록 중요해지고 있는데 반해 모빌리티 환경에서 네트워크의 불안정성은 상상을 초월하는 복잡한 문제입니다. 문제가 발생해도 재현하기 어렵고 논리적인 코드만으로는 상황을 유추하기 어려운 일이 다반사입니다.
② 고난이도의 미디어처리 영역
1:1 통화 서비스가 아닌 화상회의나 방송 서비스를 개발하려면 다양한 미디어 처리를 위한 서버들이 필요합니다. 또한 경쟁사들과 차별화를 두기 위해서 화면 꾸미기 같은 특수효과가 필요하기도 합니다. 이러한 기술은 WebRTC와는 무관하지만, 상품성 있는 서비스를 위해서는 반드시 갖춰야 하죠. 보통의 WebRTC 기반 라이브 스트리밍 서비스에서 필요로 하는 미디어 처리 흐름은 그림과 같습니다.
[그림 2] WebRTC 기반 라이브 스트리밍 서비스 미디어 처리 흐름‘송출’에서 ‘Origin’에 이르는 부분과 ‘Edge’에서 ‘수신’에 이르는 과정만이 WebRTC가 관여하는 부분이고 나머지는 모두 각자의 플랫폼과 각자의 방식으로 구현하거나 감안해야 하는 영역입니다.
WebRTC는 클라이언트에서 미디어에 변화를 많이 주고, 서버의 경우 미디어 전송이나 분배에 더 집중하지만, 서버도 녹화나 기본적인 수준의 미디어 처리는 필요할 때가 많습니다. 이 때문에 조직 내에 미디어를 자유롭게 다룰 수 있는 엔지니어도 필요하고 모바일 플랫폼의 입출력 미디어 장치에 대한 경험을 가진 엔지니어도 필요합니다.
WebRTC를 적극적으로 활용하는 서비스들은 사용자와의 인터랙션을 적극적으로 유도하는 경우가 많습니다. 이를 위해서는 영상만 실시간으로 제공되기보단 필수적으로 실시간 채팅과 같은 메시징 인프라가 제공되어야 합니다. 즉, 채팅이나 화면효과 그리고 사용자의 여러 가지 이벤트 등을 실시간으로 전파하고 공유할 수 있는 서버가 꼭 갖춰져야 합니다.
③ 대용량 처리 및 클라우드
WebRTC 미디어 서버는 WebRTC 기반의 미디어 스트림을 중개 및 분배하는 역할을 하는 서버입니다. WebRTC 기반의 방송과 화상회의형 서비스는 이 미디어 서버가 꼭 필요합니다. Janus나 Pion등과 같이 유명한 오픈소스가 존재하여 비교적 쉽게 데모 수준의 서비스를 구현해볼 수 있습니다.
미디어 서버 덕분에 1:N이나 N:N 방식의 서비스를 구현할 수는 있지만 문제는 서비스 오픈 이후에 있습니다. 즉 대용량 처리를 위한 적절한 아키텍처를 고민해야 합니다. WebRTC 기반 서비스들은 한번 방송에 몇십만 명이 시청하는 서비스보다는 클럽하우스나 아프리카TV처럼 다수의 방송이 독립적으로 존재하고 적게는 2-4명 많게는 몇천 명이 대화하는 서비스가 주를 이룹니다. 따라서 개별 방에 대한 트랜잭션을 미리 예측하거나 대응하기보다는 확장성(Scalability)을 매우 유연하게 제어하고 자동화하는 방식을 고민해야 합니다.
하지만 우리가 많이 쓰고 있는 AWS(Amazon Web Service)나 GCP(Google Cloud Platform) 혹은 카카오 i 클라우드와 같은 클라우드 서비스등을 WebRTC 미디어 서버에 적합하게 아키텍처를 구성하기는 여의치 않습니다. 적지 않은 부분부터 새롭게 고민해야 합니다. 더구나 미디어 서버를 클라우드 서비스에 적합하게 구성한다는 것은 매우 큰 도전과제 중 하나입니다.
WebRTC 응용 서비스 개발 방법
① CPaaS를 활용하기
위와 같은 이유로 인해 클럽하우스를 비롯한 많은 성공 서비스는 WebRTC 기술과 인프라를 전문적으로 제공하는 CPaaS(Communication Platform as a Service)를 활용하고 있습니다. 매우 현명한 방법이라고 생각합니다. WebRTC 응용 서비스에서 성공을 결정하는 핵심은 WebRTC가 아니라 콘텐츠 자체이기 때문입니다. 핵심에 집중하기 위하여 WebRTC 같은 매우 전문화된 기술은 클라우드 기업에 맡기는 것이죠.
해외의 경우 Twilio나 Agora.io가 유명하고 국내의 경우 Kakao i Connect Live가 유일한 CPaaS입니다. 이들 CPaaS를 이용하면 WebRTC 응용 서비스 개발에서 WebRTC와 관련된 거의 모든 부분에서 도움을 받을 수 있습니다. 웹 뿐만 아니라 모바일 플랫폼 지원과 대용량 트랜잭션 제어 그리고 미디어 서버 및 TURN서버 등을 지원받게 됩니다. 이는 WebRTC 개발자 2-3명을 채용하는 것과 동일한 효과가 있습니다.
때문에 클럽하우스 등을 포함하여 많은 WebRTC 응용 서비스는 CPaaS로 빨리 개발하고 나중에 서비스가 성공했을 때 투자 유치 후 기술 내재화 여부를 결정하게 됩니다.
② 직접 WebRTC 서비스 개발에 도전하기
WebRTC 응용 서비스들은 사용자에게 차별화된 경험을 줄 수 있고 일반 서비스보다는 진입하는 데 장벽이 있으므로 욕심 있는 엔지니어라면 한번 도전해 봄직한 분야입니다. 더욱이 WebRTC 덕분에 이전보다 라이브 스트리밍 혹은 통화 서비스를 개발하기가 한결 쉬워지고 저렴해진 것이 사실입니다. 하지만 처음에 쉽게 개발해볼 수 있다고 접근했다가 그 끝을 알 수 없는 깊이에 반 평생을 바치는 경우가 제 주위에는 적지 않습니다. 만약 WebRTC를 제대로 개발 하려면 최소 5년에서 10년 이상은 단단히 공부 할 각오를 해야 합니다. 국내에도 카카오엔터프라이즈를 비롯하여 유수의 기업들이 점점 더 WebRTC의 연구 개발에 뛰어들고 있으며, 앞으로 WebRTC 개발자는 더욱더 많이 필요하게 될 것입니다. 구글 등 외국의 경우에도 WebRTC 개발자는 항상 부족하고 관련 엔지니어 상시 채용 공고가 열려있기도 합니다.
마치며
WebRTC 기반 서비스 시장은 매년 30% 이상 성장하고 있으며 우리는 어쩌면 WebRTC가 혁신할 변화의 시작 부분에 있을지도 모르겠습니다. 세상은 훨씬 더 많은 WebRTC 엔지니어를 필요로 합니다. WebRTC 공부를 처음 시작하려고 하시는 분들을 위해 오늘 포스팅이 조금이나마 도움이 되었으면 좋겠습니다. WebRTC와 관련된 주요 링크도 공유드리니 참고하시면 좋을 것 같습니다. 마지막으로 카카오엔터프라이즈에서도 WebRTC 개발자를 채용하고 있으니 많은 분들의 지원을 기다리겠습니다. 그럼 WebRTC로 이어질 미래를 기대해 보며 글을 마치도록 하겠습니다.
📍 개발자를 위한 주요 링크
✓ https://WebRTC.org – WebRTC 공식 사이트
✓ https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API WebRTC API 모질라 문서
✓ https://webrtc.googlesource.com/src WebRTC 프로젝트 마스터 repo
✓ https://webrtcforthecurious.com/ WebRTC의 이론을 상세하게 공부하기 좋은 문서
✓ https://webrtcweekly.com/ WebRTC 뉴스를 가장 빠르게 접할 수 있는 뉴스레터
✓ https://bloggeek.me/ 가장 유명한 WebRTC 블로거 Tsahi의 블로그
✓ https://www.facebook.com/groups/rtc.korea 한국 WebRTC 커뮤니티
✓ https://connectlive.kakaoi.ai/ 카카오 엔터프라이즈에서 제공하는 CPaaS, Kakao i Connect Live
새로운 길에 도전하는 최고의 Krew들과 함께 해요! WebRTC 개발자 영입
최진호(Green) WebRTC와 geek 문화를 좋아합니다.
PlayRTC, 리모트몬스터를 거쳐 Kakao i ConnectLive까지 3번째 WebRTC CPaaS를 만들어오고 있습니다.
WebRTC는 어떻게 실시간으로 데이터를 교환할 수 있을까?
최근에 합류한 스타트업에서는 WebRTC를 활용한 반려동물 모니터링 웹뷰 어플리케이션을 만들고 있습니다.
하지만 안타깝게도 저는 반려동물이 없기 때문에(…) 집에 있는 인어킹 인형이 포효하는 영상을 찍어보았습니다
사실 저 역시도 WebRTC에 대해서 아는 것이 전혀 없는 상태에서 시작한 프로젝트였습니다. 결국 처음에는 WebRTC 자체에 대한 이해 없이 일단 돌아가기만 하는 코드 를 만들게 되었습니다. 이 때문에 기술 부채를 많이 졌지만, 다행히도 지금은 열심히 리팩토링을 해서 빚을 다 청산한 상태입니다. 덕분에 현재는 간단한 화상 통화 어플리케이션을 제작하고 유지보수할 수 있는 수준이 되었습니다.
하지만 WebRTC에서 등장하는 낯선 용어들을 아직 완벽하게 정복하지는 못했습니다. 이 때문에 오늘 포스트에서는 WebRTC가 어떤 절차를 통해 연결되고, 이 과정에서 등장하는 낯선 용어들에 대해 정리해보고 넘어가는 시간을 갖고자 합니다. 이번 포스트를 통해 WebRTC에 관심이 있으신 프론트엔드 개발자 분들께 도움이 되기를 바랍니다.
결론부터 이야기하자면
WebRTC가 실시간으로 웹에서 데이터를 교환할 수 있는 이유는 시그널링이라고 일컫어지는 NAT 우회 과정을 거치기 때문입니다.
MDN의 WebRTC 문서에서는 WebRTC를 다음과 같이 정의하고 있습니다.
WebRTC(Web Real-Time Communication) 은 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 포착하고 마음대로 스트림 할 뿐 아니라, 임의의 데이터도 교환할 수 있도록 하는 기술입니다.
한마디로 요약하자면 드라이버나 플러그인 설치 없이 웹 브라우저 간 P2P 연결을 통해 데이터 교환을 가능하게 하는 기술입니다. 이 WebRTC의 등장과 발전은 개인화된 웹을 상징하는 웹 3.0과도 같은 길을 걷고 있는데요.
월드 와이드 웹(World Wide Web)이 1990년대에 처음 등장했을 때, 웹은 단순히 하이퍼링크로 연결된 정적인 문서 기반의 모델이었습니다. 그러다가 2000년대 중반에 이르러서는 XHR(XMLHttpRequest) 방식을 통해 페이지 전환 없이 동적으로 데이터를 받아올 수 있게 되면서, 웹은 동적인 어플리케이션을 제작할 수 있는 플랫폼이 되었습니다. 이때 등장한 웹 어플리케이션들이 바로 지메일이나 페이스북, 트위터 같은 것들이 있죠.
WebRTC는 기존의 웹 2.0에서 한층 더 나아가, 서버와 같은 중간자를 거치지 않고 브라우저 간을 P2P로 연결하는 기술입니다. 사실 우리에게 낯설지 않은 기술들인 화상 통화와 실시간 스트리밍, 파일 공유, 스크린 공유 등이 WebRTC를 기반으로 하고 있습니다. P2P 연결은 중개 서버를 거치지 않기 때문에 빠른 속도가 보장되며, HTTPS가 강제되기 때문에 중간자 공격에 대한 보안이 보장됩니다. 그리고 실시간으로 상호작용 할 수 있다는 특성을 바탕으로 더욱 개인화되고 참여 유도적인 웹 어플리케이션을 제작할 기회가 되기도 합니다.
P2P 연결에서는 속도와 보안, 효율성을 고려해야겠지만, WebRTC가 범용적으로 사용되기 위해서는 다양한 플랫폼과 브라우저에서 접속하는 사용자들에게 동일한 사용자 경험을 제공하는 일이 첫 번째일 것입니다. 때문에 WebRTC에서 브라우저와 플랫폼 간 호환성은 가장 큰 숙제일 수밖에 없습니다.
브라우저 호환성
WebRTC는 구글이 주도한 오픈소스 프로젝트를 기반으로 하는 웹 표준이기 때문에, 특히 크롬(Chrome)에서 호환성이 높습니다. 그리고 파이어폭스(Firefox)와 오페라(Opera) 등이 WebRTC 표준을 적극적으로 후원하고 있죠. 한편 사파리(Safari) 역시 WebKit 기반 브라우저이기 때문에 WebRTC가 지원되기는 하지만, 애플의 정책이 늘 그렇듯 다른 브라우저에 비해 호환성도 가장 떨어지고 기본으로 지원해주는 설정들이 적은 편입니다. 그래서 저는 사파리를 럭키 IE(…) 라고 부르곤 합니다.
즉 WebRTC는 아직까지 다양한 플랫폼에서 표준화가 완전히 구현되지는 않은 기술입니다. 정확히 이야기하자면 WebRTC 자체는 1.0 버전의 표준이 있지만, 이 규격을 모두 준수하는 플랫폼들이 아직까지 많지 않습니다. 그러니까 브라우저와 운영체제 별로도 호환성과 상호 운용성이 상이하다는 이야기죠. 그래서 각 브라우저의 WebRTC API에는 moz , webkit 같은 벤더 프리픽스(vendor prefix)가 붙어있습니다.
이런 크로스 브라우징 이슈를 해결하기 위해서는 adapter.js 라이브러리를 함께 사용하는 것이 필수적입니다. 이 라이브러리는 shim 패턴 및 폴리필을 이용해 다양한 브라우저에서 발생할 수 있는 크로스 브라우징 이슈를 사전에 처리해줍니다. 또한, 벤더 프리픽스를 신경 쓸 필요 없이 동일한 API를 호출할 수 있게 만들어 주기 때문에, 코드 컨벤션 유지와 개발 생산성 향상에서도 큰 도움을 줍니다.
결론적으로 WebRTC는 단일 브라우저 벤더에서 제공하는 API가 아니며, 브라우저와 운영체제별로 개발되는 속도와 지원되는 버전이 다르므로 호환성과 상호 운용성을 항상 체크해야 합니다.
P2P 절차
WebRTC는 P2P 방식의 커뮤니케이션이기 때문에 각각의 웹 브라우저는 다음과 같은 절차를 밟아야 합니다.
각 브라우저가 P2P 커뮤니케이션에 동의 서로의 주소를 공유 보안 사항 및 방화벽 우회 멀티미디어 데이터를 실시간으로 교환
여기에서 우리는 2번과 3번 단계가 일반적인 웹 개발의 접근 방법으로는 해결하기 어렵다는 것을 확인할 수 있습니다. 왜냐하면 브라우저는 웹 서버가 아니기 때문에, 외부에서 접근할 수 있는 주소가 없기 때문이죠. 때문에 WebRTC가 P2P 기반이긴 하지만 통신 설정 초기 단계에서는 중재자의 역할이 필요합니다.
방화벽과 NAT 트래버셜
일반적인 컴퓨터에는 공인 IP가 할당되어 있지 않습니다. 그 원인으로는 방화벽(Firewall), 여러 대의 컴퓨터가 하나의 공인 IP를 공유하는 NAT, 유휴 상태의 IP를 일시적으로 임대받는 DHCP 때문입니다. 이 때문에 단순히 공인 IP만을 알아낸다고 해서, 특정한 사용자를 가리킬 수는 없습니다. 공인 IP뿐만 아니라 해당 네트워크에 연결된 사설 IP 주소까지 알아내야 특정한 사용자를 지정할 수 있게 되죠.
일반적으로는 라우터가 NAT 역할을 합니다. 외부에서 접근하는 공인 IP와 포트 번호를 확인하여 현재 네트워크 내의 사설 IP들을 적절히 매핑시켜주죠. 그러니까 어떤 브라우저 두 개가 서로 직접 통신을 하려면, 각자 현재 연결된 라우터의 공인 IP 주소와 포트를 먼저 알아내야 합니다.
하지만 어떤 라우터들은 특정 주소나 포트와의 연결을 차단하는 방화벽 설정이 되어 있을 수도 있습니다. 이처럼 라우터를 통과해서 연결할 방법을 찾는 과정을 NAT 트래버셜(NAT traversal)이라고 합니다.
STUN, TURN
STUN 방식 vs TURN 방식
이 NAT 트래버셜 작업은 STUN(Session Traversal Utilities for NAT) 서버에 의해 이루어집니다. STUN 방식은 단말이 자신의 공인 IP 주소와 포트를 확인하는 과정에 대한 프로토콜입니다. 즉, STUN 서버는 인터넷의 복잡한 주소들 속에서 유일하게 자기 자신을 식별할 수 있는 정보를 반환해줍니다. 즉, WebRTC 연결을 시작하기 전에 STUN 서버를 향해 요청을 보내면, STUN 서버는 NAT 뒤에 있는 피어(Peer)들이 서로 연결할 수 있도록 공인 IP와 포트를 찾아줍니다.
쉽게 말해서 다른 사람이 우리 집에 쉽게 찾아올 수 있도록 사전에 우리 집 주소를 조회해서 알아내는 것과 같습니다. 만약 두 개의 장치가 성공적으로 STUN 서버에서 자기 자신의 주소를 알아냈을 경우에는 P2P 연결을 시도할 두 개의 고유한 주소가 생긴 셈입니다.
하지만 STUN 서버를 이용하더라도 항상 자신의 정보를 알아낼 수 있는 것은 아닙니다. 어떤 라우터들은 방화벽 정책을 달리 할 수도 있고, 이전에 연결된 적이 있는 네트워크만 연결할 수 있게 제한을 걸기도 합니다(Symmetric NAT). 이 때문에 STUN 서버를 통해 자기 자신의 주소를 찾아내지 못했을 경우, TURN(Traversal Using Relay NAT) 서버를 대안으로 이용하게 됩니다.
TURN 방식은 네트워크 미디어를 중개하는 서버를 이용하는 것입니다. TURN 방식은 중간에 서버를 한 번 거치기 때문에, 엄밀히 이야기하자면 P2P 통신이 아니게 되며 그 구조상 지연이 필연적으로 발생하게 됩니다. 하지만 보안 정책이 엄격한 개인 NAT 내부에 위치한 브라우저와 P2P 통신을 할 수 있는 유일한 방법이기 때문에, TURN 방식은 최후의 수단으로 선택되어야 합니다.
여태껏 이야기한 STUN, TURN 서버를 이용해서 획득했던 IP 주소와 프로토콜, 포트의 조합으로 구성된 연결 가능한 네트워크 주소들을 후보(Candidate) 라고 부릅니다. 그리고 이 과정을 후보 찾기(Finding Candidate)라고 부릅니다.
이렇게 후보들을 수집하면 일반적으로 3개의 주소를 얻게 됩니다.
자신의 사설 IP와 포트 넘버
자신의 공인 IP와 포트 넘버 (STUN, TURN 서버로부터 획득 가능)
TURN 서버의 IP와 포트 넘버 (TURN 서버로부터 획득 가능)
한편, 이 모든 과정은 ICE(Interactive Connectivity Establishment) 라는 프레임워크 위에서 이루어집니다. ICE는 두 개의 단말이 P2P 연결을 가능하게 하도록 최적의 경로를 찾아주는 프레임워크입니다.
지금까지의 내용을 요약하자면, ICE 프레임워크가 STUN, 또는 TURN 서버를 이용해 상대방과 연결 가능한 후보들을 갖고 있다는 것입니다. 그러니까 두 브라우저가 P2P 통신을 위해 통신할 수 있는 주소만큼은 확실하게 알아낸 셈입니다. 따라서 마지막으로 남은 것은 이제 미디어와 관련된 정보를 교환하는 것입니다.
SDP
직렬화된 SDP 데이터. JS에서 읽기 쉽게 보려면 별도의 라이브러리를 쓰는 것이 좋습니다.
SDP(Session Description Protocol) 는 WebRTC에서 스트리밍 미디어의 해상도나 형식, 코덱 등의 멀티미디어 컨텐츠의 초기 인수를 설명하기 위해 채택한 프로토콜입니다. 화상 통화 어플리케이션을 예시로 들어보자면 웹캠 비디오의 해상도를 보낼 수 있고, 오디오 전송 또는 수신 여부를 보낼 수도 있겠죠.
이처럼 미디어와 관련된 초기 세팅 정보를 기술하는 SDP는 발행 구독 모델(Pub/Sub)과 유사한 제안 응답 모델(Offer/Answer) 을 갖고 있습니다. 그러니까 어떤 피어가 이러한 미디어 스트림을 교환할 것이라고 제안 을 하면, 상대방으로부터 응답 이 오기를 기다린다는 의미입니다.
그렇게 응답 을 받게 되면, 각자의 피어가 수집한 ICE 후보 중에서 최적의 경로를 결정하고 협상하는 프로세스가 발생합니다. 수집한 ICE 후보들로 패킷을 보내 가장 지연 시간이 적고 안정적인 경로를 찾는 것이죠. 이렇게 최적의 ICE 후보가 선택되면, 기본적으로 필요한 모든 메타 데이터와 IP 주소 및 포트, 미디어 정보가 피어 간 합의가 완료됩니다.
이 과정을 통해 피어 간의 P2P 연결이 완전히 설정되고 활성화됩니다. 그 후 각 피어에 의해 로컬 데이터 스트림의 엔드포인트가 생성되며, 이 데이터는 양방향 통신 기술을 사용하여 최종적으로 양방향으로 전송됩니다.
이 과정에서 NAT의 보안 이슈 등으로 최선의 ICE 후보를 찾지 못할 수도 있기 때문에, 이때에는 폴백으로 세팅한 TURN 서버를 P2P 대용으로 설정합니다.
통신에 TURN 폴백을 사용할 때 각 피어는 굳이 귀찮게 P2P로 데이터를 연결하고 전송하는 방법을 알 필요가 없습니다. 대신, 통신 세션 중에 실시간 멀티미디어 데이터를 중개하는 공용 TURN 서버를 알고 있어야 합니다.
Trickle ICE
Trickle은 물이 가늘게 똑똑 떨어지고 있다는 의미입니다
한편, ICE 프레임워크를 설정하다보면 Trickle ICE 라는 옵션을 심심치않게 만나볼 수 있습니다. 위의 사진을 참고했을 때, 이 단어가 혹시 무슨 옵션인지 짐작이 가시나요?
일반적으로 각 피어는 ICE 후보들을 수집해서 그 목록을 완성한 후 한꺼번에 교환하게 됩니다. 하지만 이러한 방식은 SDP의 제안 응답 모델과 맞물리면서 단점으로 작용합니다.
후보를 모으는 데에도 시간이 오래 걸리고, 그 과정에서 네트워크 환경에 따라 지연이 걸릴 수 있습니다. 또한 한 쪽 피어의 ICE 후보 수집 작업이 완료되어야만 다른 피어가 ICE 후보를 모을 수 있기 때문에 비효율적이죠.
이러한 비효율적인 후보 교환 작업을 병렬 프로세스로 수행할 수 있게 만드는 것이 바로 Trickle ICE 입니다. 두 개의 피어가 ICE 후보를 수집하고 교환하는 과정을, 동기적 프로세스 에서 비동기적 프로세스 로 만드는 기술이라고 이야기할 수 있겠네요.
즉, Trickle 옵션이 활성화된 ICE 프레임워크는 각 피어에서 ICE 후보를 찾아내는 그 즉시 교환을 시작합니다. 그래서 상호 간 연결 가능한 ICE를 보다 빨리 찾아낼 수 있죠. 이러한 옵션 덕분에 ICE 프레임워크는 피어 간의 연결 상태를 체크함과 동시에 연결에 걸리는 시간을 최적화할 수 있습니다. 결론적으로 Trickle 옵션은 가능하다면 활성화하는 게 좋겠죠?
한편 WebRTC 한글 문서에서는 이를 직역해서 물방울 ICE라고 부르는 모양이네요.
시그널링
위에서 이야기한 모든 과정을 일컬어 시그널링(Signaling)이라고 부릅니다. 즉 RTCPeerConnection 통신에 사용할 프로토콜, 채널, 미디어 코덱 및 형식, 데이터 전송 방법, 라우팅 정보와 NAT 통과 방법을 포함한 통신 규격을 교환하기 위해 두 장치의 제어 정보를 교환하는 과정을 의미합니다.
위의 과정을 보면 알 수 있듯이 시그널링은 WebRTC 자체에서 지원하는 기능이 아닙니다. WebRTC 연결 전 미리 준비해야 하는 과정입니다. WebRTC 자체의 스펙도 아니기 때문에, 한 가지로 딱 정해진 방법이 없습니다. 정해진 방법이 없는 이유는 알 수 없는 두 장치가 언제 어떤 방식으로 연결될 수 있는지의 모든 경우를 예측하는 것이 불가능하기 때문입니다. 그래서 개발자는 자신에게 맞는 최적의 방법을 선택적으로 적용할 수 있죠.
이 때문에 일반적으로 두 개의 장치를 연결할 수 있는 시그널링 서버를 직접 구축하거나, 시그널링 서버를 제공해주는 외부 솔루션을 적용할 수 있습니다.
만약 시그널링 서버를 직접 구축한다면 웹 소켓(Web Socket)이나 서버 전송 이벤트(Server-sent Event) 방법을 적용할 수 있습니다. 시그널링 정보를 조회할 수 있는 API를 만든 후 브라우저 단에서 주기적으로 XHR을 요청하는 폴링(polling) 기법을 쓸 수도 있죠. 이 외 시그널링 서버의 구현 방법들로는 이곳을 참고해주세요.
한편 WebRTC를 처음 접하는 개발자에게는 오히려 표준이 없다는 것이 혼란을 일으키곤 하죠. 서버를 직접 구축하는 것도 일이 되구요. 때문에 시그널링 서버를 제공해주는 솔루션을 쓰는 것도 방법이 될 수 있습니다. 아마존의 Kinesis Video Stream 이 대표적인 예시이고, 구글의 AppRTC에서는 Google App Engine으로 구현된 시그널링 서버를 확인할 수 있습니다.
한계
제가 제일 좋아하는 TCP vs UDP 비교 짤
그렇다고 해서 WebRTC의 현실이 밝은 것만은 아닙니다.
첫 번째는 역시 브라우저 간 호환성 입니다. 아직 adapter.js 같은 라이브러리 없이는 다양한 브라우저의 호환성을 장담할 수 없습니다. 특히 사파리와 IE, 엣지가 그러하죠.
다음으로는 시그널링 서버에 대한 명시적인 표준이 없습니다. 개발자의 능력과 자율성에 맡겨둔 부분이 오히려 처음 WebRTC를 입문하는 사람들에게 혼란을 일으키기도 합니다.
마지막으로는 WebRTC는 기본적으로 실시간성이 매우 중요하기 때문에 UDP 위에서 동작합니다. 즉 데이터를 빠르게 전송할 수는 있지만, 이 과정에서 발생한 데이터 손실이 발생할 수도 있죠. 비디오라던가 오디오에 있어서 몇 프레임 정도가 끊기는 것은 큰 문제가 되지 않지만, 중요한 파일들을 전송할 때에는 이 데이터 손실이 문제를 일으킬 수도 있습니다. 작은 몇 바이트의 데이터 손실 때문에 전체 파일이 동작하지 않는 문제가 생길 수도 있죠. (TCP 방식을 사용할 수도 있지만 UDP를 사용할 수 없거나 미디어 스트리밍에 적합하지 않은 방식으로 제한되는 경우에만 사용되고, 모든 브라우저가 TCP 방식을 지원하는 것도 아닙니다.)
마무리
사실 저도 어렵게 느껴져요
그럼에도 불구하고 브라우저에서 P2P 통신을 가능하게 해주는 기술인 WebRTC는 앞으로의 발전이 더 기대되는 기술입니다.
사실 WebRTC에 관한 원리와 이론적인 내용을 다루다 보니, 제가 썼지만 상당히 재미가 없네요. 약간 학교 다닐 때 컴퓨터 네트워크 강의를 들었던 것이 어렴풋이 생각도 나네요.
재밌는 글은 아니지만 WebRTC와 관련된 한글 자료가 많이 없는 곳에서 이 글이 조금이나마 도움이 되기를 바랍니다.
참고자료
위키백과, 우리 모두의 백과사전
WebRTC(Web Real-Time Communication)는 웹 브라우저 간에 플러그인의 도움 없이 서로 통신할 수 있도록 설계된 API이다. W3C에서 제시된 초안이며, 음성 통화, 영상 통화, P2P 파일 공유 등으로 활용될 수 있다.
역사 [ 편집 ]
웹 브라우저 기반의 통신 방식인 WebRTC는 구글이 오픈 소스화한 프로젝트에서 기원하였다.[3] 그 뒤로 국제 인터넷 표준화 기구[4]가 프로토콜 표준화 작업을, W3C가 API 정의를 진행하였다.[5]
WebRTC의 W3C 초안[6] 작업은 진행 중이며 크롬과 파이어폭스 브라우저에서 먼저 구현되고 있다. API는 WHATWG[7]과 에릭슨.[8]의 작업에 기반하여 정의되었다.
개요 [ 편집 ]
설계 [ 편집 ]
WebRTC의 주요 구성 요소는 여러 자바스크립트 API를 포함하고 있다:
getUserMedia : 오디오와 비디오 미디어를 가져온다. (예: 장치의 카메라와 마이크로폰에 접근하여) [9]
: 오디오와 비디오 미디어를 가져온다. (예: 장치의 카메라와 마이크로폰에 접근하여) RTCPeerConnection : 피어 간 오디오, 비디오 통신을 활성화한다. 신호 처리, 코덱 관리, P2P 통신, 보안, 대역폭 관리를 수행한다. [10]
: 피어 간 오디오, 비디오 통신을 활성화한다. 신호 처리, 코덱 관리, P2P 통신, 보안, 대역폭 관리를 수행한다. RTCDataChannel : 피어 간 양방향 임의 데이터 통신을 허용한다. 웹소켓과 동일한 API를 사용하며 매우 낮은 레이턴시를 보인다.[11]
또, WebRTC API는 통계 함수를 포함한다:
getStats : 웹 애플리케이션에 WebRTC 세션에 관한 통계 집합의 검색을 허용한다. 이 통계 데이터는 별도의 W3C 문서에 기술되어 있다.[12]
지원 [ 편집 ]
WebRTC는 다음의 브라우저에서 지원된다:
2013년 10월 마지막 기능 릴리스 이전의 인터넷 익스플로러에서는 지원되지 않으나,[18] 서드파티 플러그인을 사용하여 인터넷 익스플로러와 macOS용 사파리에서 WebRTC 지원을 추가할 수 있다.[19][20] WWDC 2017에서, 애플은 사파리 11에서 WebRTC를 지원할 것이라고 발표했으며,[15] 사파리 테크놀로지 프리뷰 릴리스 32에서 사용 가능하게 되었다.[21]
참조 [ 편집 ]
웹RTC 6년,어제와 오늘 그리고 미래 (1)
웹RTC 6년,어제와 오늘 그리고 미래 (1)
웹RTC(WebRTC, Web Real Time Communication), 플러 그인이나 설치 없이 브라우저만으로 실시간 화상통화와 데이 터 통신을 할 수 있다는 그 매력에 빠진 사람들은 수년간 입에 달고 살았을 기술. 이렇게 이야기를 시작하는 이유는 우리나라 의 여러 환경이 웹RTC를 하기에는 많이 어려웠기 때문이다.
이걸 다른 방법으로 풀어 성공한 국내 회사도 있긴 하지만. 2017년은 웹RTC가 사업성을 더욱 확보하게 되는 중요한 시 기다. 웹RTC 표준이 완성되는 해이고, 애플 사파리(Safari) 11 이 웹RTC 지원을 시작하기 때문이다. 웹RTC에 대해 잘 모르 는 이들을 위해, 또 아는 사람들은 그 가치를 한번 되짚어보는 의미에서 웹RTC의 어제를 살펴보겠다.
웹RTC의 미션
개발자도 아닌데 어쩌다보니 작년부터 스스로를 웹RTC 비 저니스트(Visionist)라고 하면서 동향과 이슈에 대해 발표하고 다니는데, 그때마다 가장 먼저 하는 얘기가 있다. 바로“‘웹 RTC의 미션’이 뭔지 아느냐”다. 구글이 웹RTC 공식사이트에 적어놨지만 적잖은 이들이 무심코 지나쳤을 그 미션은 다음과 같다.
“To enable rich, high-quality RTC applications to be developed for 1) the browser, 2) mobile platforms, and 3) IoT devices, and 4) allow them all to communicate via a common set of protocols.”
첫 번째는 브라우저 간의 고품질 실시간 통신 서비스 개발을 위해, 두 번째는 모바일, 세 번째는 IoT, 그리고 결국 일반 프로 토콜셋을 통해 이 모두가 통신하도록 만드는 것이다. 웹RTC의 활용분야가 어디까지가 될지 알 수 있는 중요한 미션이라고 하 겠다.
웹RTC의 생김새
웹RTC가 많이 알려지긴 했지만, 아직 모르는 개발자들도 많 이 있는 게 사실이다. 화상회의를 오랫동안 개발하던 사람들 도, 웹개발을 하는 사람들도 잘 모르는 경우가 많아서, 기본적 인 것들 중에 필요한 부분을 알아보겠다.
먼저, 웹RTC 아키텍처를 먼저 보는 게 좋을 거 같다. 아키텍 처 그림은 구글의 것을 조금 업데이트한 것이다. 이 그림에서 웹RTC의 영역은 음성엔진, 비디오엔진, 전송 영역에 세션 컨트 롤(Session Control), 웹RTC C++ API 등으로 돼있는데, 통상 웹RTC라고 하면 밖에 있는 웹 API까지를 포함한 것을 말한다
웹API는 자바스크립트로 돼있으며, 이 표준에 대한 문서는 W3C에서 작성한다. 그래서 우리가 웹RTC 표준이라고 하면 보통 이 W3C의‘WebRTC 1.0: Real-time Communication Between Browsers’를 말하는 것이고, 그렇기 때문에 웹개발 자가 간단한 웹 API만으로 브라우저를 통해 실시간 통신 애플 리케이션을 만들 수 있게 되는 것이다. 이것은 매우 중요한 웹 RTC의 장점 중 하나다.
웹RTC (네이티브) C++ API는 미디어스트림(Media Stream)과 피어커넥션(Peer Connection)으로 구성됐다. 이건 누가 만드는 걸까 브라우저 개발사에서 만든다. Webrtc.org 에는 구글의 네이티브 API가 있고, 그것을 통해 웹RTC 호환 브라우저나 응용프로그램을 만들 수 있다.
아키텍처에서 또 중요하게 생각하는 부분은, 보이스엔진과 비디오엔진 부분에 실시간 전송을 위한 기술들이 포함됐다는 점이다. 기존에 화상회의 솔루션을 만들 때 에코 캔슬, 노이즈 제거, 전송 지연에 대응하는 음성과 비디오 처리 기술들은 상 당한 노하우가 필요했고, 제대로 구현하는 데 상당한 시간과 인력이 요구됐다. 성능이 나오는 솔루션을 만들기 위해 오디오 와 비디오 처리에 수십 명 이상의 박사급 개발자들이 있어야 했다.
다시 한 번 생각해보라. 지금 변화무쌍한 환경의 인터넷 위 에 실시간 화상통신 솔루션을 개발해고자 한다면, 위 아키텍처 그림에 있는 미디어와 데이터 전송을 처리하기 위한 기술들과 노하우를 알기까지 얼마나 많은 시간이 걸릴지 말이다. 그런데 웹RTC에는 이미 그런 기술들이 포함돼 있으니, 아이디어만 있 으면 HTML과 자바스크립트로 실제 사용할 수 있는 것을 개발 할 수 있다. 시간과 비용을 줄이고 빨리 원하는 서비스나 제품 을 만들 수 있는 것이다.
짧게 보는 웹RTC의 역사와 의의
웹RTC의 역사에 대해서는 이제 인터넷에서 많이 찾아 볼 수 있다. 그럼에도 언급하고 넘어가야 하는 이유는, 오늘날의 웹 RTC가 되기까지 우여곡절을 살펴봄으로써 앞으로 그 영역확 장에 있어 가속도가 더 붙게 될 것임을 짐작할 수 있기 때문이 다.
2010년 구글은 웹만으로 비디오와 오디오 실시간 통신이 가 능한 프로젝트를 진행하기 위해 2개 회사를 인수한다. 인수 후 가장 먼저 한 것은, 현재 VP8 코덱의 전신인 웹M 프로젝트를 진행하며 비디오 코덱을 오픈소스로 만든다. 이듬해에는 웹 RTC 표준을 제안, W3C에 워킹그룹(WG)이 만들어진다. 2013년에는 파이어폭스(Firefox)가 웹RTC를 적극 지원한 다. 그런데 마이크로소프트(MS)에서 웹RTC에 대항하는 ORTC라는 표준을 제안한다. 이에 웹RTC 생태계에서는 웹 RTC 시장이 갈라지는 것을 우려했고, 웹RTC와 ORTC 두 가 지를 모두 해야 되는지 고민했다.
2015년은 웹RTC의 성능 향상이 컸던 시기다. 또한 웹RTC 관련 벤더들 간 교류도 활발하게 진행됐다. 이때 중요했던 이 슈 중 하나는 HTTPS였다. 구글은 웹RTC의 보안을 강화하기 위해 크롬에서 카메라나 오디오 장치를 불러오려면 HTTPS에 서만 가능하게 했다. 지금은 다른 브라우저들도 HTTPS에서 동작한다.
2016년 들어 MS 엣지(Edge)와 크롬이 오디오 연결에 성공 한다. 구글과 MS가 협력하고 있음을 알리는 신호탄이었다. ‘TPAC 2016 리스본’에서는 웹RTC의 다음 버전에 대한 고려 사항이 거론된다. 웹AR/VR 지원 등 다양한 논의가 있었고, 다 음 버전이 어떻게 진행될지 알 수 있는 중요한 행사였다. 구글 과 MS는 웹RTC와 ORTC가 서로 호환되도록 하기 위해 협력 하고 있으며, 향후에는 서로의 장점을 결합해 웹RTC 다음 버 전으로 통합한다는 계획이다. 그리고 2017년 MS 엣지가 웹 RTC 1.0 표준과 VP8 코덱을 지원한다. 웹RTC 표준이 연말까 지 완성될 예정이다. 웹RTC가 사업성을 더욱 갖게 된다.
그동안의 걸림돌은 해결됐다
그동안 웹RTC 사업 관련 걸림돌들과, 이에 대한 현재 상황 은 다음과 같다.
– 미지원 브라우저 : MS 엣지와 애플 사파리가 지원하게 됨 에 따라 대부분의 브라우저가 지원하게 됐다. 문제가 됐던 인터넷익스플로러(IE) 지원은 이전엔 플러그인과 플래쉬를 활용할 수 있었으나, 이제는 nw.js를 이용해 원소스로 윈도 우 응용프로그램으로 쉽게 만들 수 있게 됐다.
– 표준 미완성 : 올 연말까지 웹RTC 1.0 표준 완성을 목표로 구글과 모질라가 바쁘게 움직이고 있다. 이전까지 일부 시 장에서는 표준이 완성되지 않아서 어떻게 될지 모르므로 사업에 적용할 수 있는 것은 아니라는 시각이 있었다. 그러 나 이제는 표준의 완성으로 다양한 클라이언트가 그 표준 에만 맞추면 실시간 비디오, 오디오, 데이터 전송 서비스를 만들 수 있게 된 것이다.
– 웹RTC 성능 : 크롬과 파이어폭스의 업데이트 주기는 평균 6~8주 정도였으며API 등이 있었다. 초창기에만 웹RTC를 접했던 이 들이 지금의 모습을 본다면 그 차이를 실감할 것이다.
– P2P를 넘어 : 웹RTC는 P2P로 1:1 통신에 최적화됐기 때 문에, 다중 참석 솔루션으로는 힘들다는 의견도 있었다. 그 러나 요즘에는 많은 인원이 참석하는 솔루션이 일반적으로 생각될 만큼 웹RTC 미디어서버(Media Server) 오픈소스 도 많은 성능 향상이 있었다. 오히려 웹RTC가 낮은 지연 시간(Low Latency)으로 각광받게 됐다.
– 모바일 : 모바일 브라우저에도 웹RTC가 지원된다. 앱을 만 들 수도 있지만, 모바일도 브라우저로 대응할 수 있다. ‘홈 에 바로가기’를 하면, 웹 주소를 입력해 서비스에 접속하는 게 아니라 터치만으로 모바일 앱처럼 실행할 수도 있다. 더 많은 이야기가 있겠지만, 1편은 이 정도로 웹RTC의 역사 와 의미를 생각해보는 것으로 마무리하겠다. 다음 편에서는 웹 RTC를 이용한 다양한 유즈케이스에 대해 다뤄보고자 한 다.
키워드에 대한 정보 웹 rtc
다음은 Bing에서 웹 rtc 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 WebRTC? WebSockets? 5분 개념정리!
- 코딩
- 프로그래밍
WebRTC? #WebSockets? #5분 #개념정리!
YouTube에서 웹 rtc 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 WebRTC? WebSockets? 5분 개념정리! | 웹 rtc, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.