ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • WebRTC 기초 개념 정리
    카테고리 없음 2024. 11. 23. 23:35
    반응형

    이 글은 WebRTC 통신 원리를 자세하게 서술한 글이 아닙니다.

    WebRTC 라이브러리를 사용하기 위해 필요한 사전 지식들을 알리는 개괄 형태의 글입니다.

     

    WebRTC

    웹 브라우저만으로 추가적인 프로그램 설치 없이 P2P로 영상 / 음성 미디어를 초저지연으로 스트리밍 할 수 있는 기술이다.

    현재 대부분의 웹 브라우저가 WebRTC를 지원하고 있다.

    아래 웹사이트에서 각 브라우저 마다 어떤 버전에서 WebRTC를 지원하고 있는지 한눈에 볼 수 있다.

    https://caniuse.com/?search=webrtc

     

     

    시그널링 (Signaling)

    영상 / 음성 스트리밍을 주고 받기 이전에 각 기기간 연결이 필요하다.

    이때 필요한 정보들을 주고 받으며 각 클라이언트 간 연결을 맺게 해주는 과정을 시그널링이라고 부른다.

     

    시그널링은 각 클라이언트가 연결된 후 진행하는 것이 아니라, 시그널링 서버가 각 클라이언트 통신을 중개하며 진행되는 과정이다. 시그널링이 끝나고 나서야 각 클라이언트가 연결되며, 서로 미디어 데이터를 송수신할 수 있다.

     

    WebRTC는 시그널링 정보를 전달하는 과정 자체를 직접 지원해주지는 않기 때문에 시그널링 서버가 필요하다.

    WebRTC RFC표준 스펙에는 시그널링 서버에 대한 표준 구현 내용이 없기 때문에 원하는 방법대로 구현하면 된다.

     

    WebRTC 시그널링은 전서구(비둘기)를 활용해서 전달해도 된다고 써있을 정도로 마음대로 만들면 된다.

    (놀랍게도 실제 mozilla 공식 문서에 씌어있는 말이다)

     

    가장 대중적인 방법으로 WebSocket을 사용해서 시그널링 정보 전달을 구현하고 있고, RestAPI 등을 활용해서 구현해도 무방하다.

    서버 개발을 하기 싫거나, 할 줄 모르는 개발자들은 Firebase의 Realtime Database를 가지고 활용해 예시로 많이 활용하는 것을 심심찮게 볼 수 있다.

     

    시그널링 과정

    시그널링 과정은 크게 2가지로 나눌 수 있으며, 이 둘이 모두 성공하면 각 클라이언트는 서로 음성/영상 스트리밍 데이터를 주고받을 수 있는 상태가 된다.

     

    1. 각 기기에 내장되어있는 미디어 정보를 담은 SDP 정보를 교환한다.

    2. ICE 과정으로 P2P 연결을 수행한다.

     

    SDP 정보 교환

    먼저 SDP는 무엇일까?

    Session Description Protocol의 약자로, 시그널링을 할 때 주고받는 미디어 정보를 기술한 데이터 형식이다.

    더 쉽게 말하면, Json 같은 것이다.

     

    <SDP의 생긴 형태> (굉장히 끔찍하게 생겼다.) (더 보기 클릭)

    더보기
    v=0
    o=- 8024579381485303156 2 IN IP4 127.0.0.1
    s=-
    t=0 0
    a=group:BUNDLE 0 1
    a=msid-semantic: WMS 1286608d-20f3-40aa-8a04-ff5b1c98a92a
    m=audio 9 UDP\/TLS\/RTP\/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
    c=IN IP4 0.0.0.0
    a=rtcp:9 IN IP4 0.0.0.0
    a=ice-ufrag:0obG
    a=ice-pwd:LvsHqE\/ZlRqnv3Nyq+xUeQHX
    a=ice-options:trickle renomination
    a=fingerprint:sha-256 A1:0E:99:B8:B4:AD:83:47:EB:51:42:32:A9:63:59:4E:07:2A:03:B4:1A:10:04:F6:A7:61:48:6B:51:D1:C6:FE a=setup:actpass
    a=mid:0
    a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
    a=extmap:2 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/abs-send-time
    a=extmap:3 http:\/\/www.ietf.org\/id\/draft-holmer-rmcat-transport-wide-cc-extensions-01
    a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
    a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
    a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
    a=sendrecv
    a=msid:1286608d-20f3-40aa-8a04-ff5b1c98a92a 1286608d-20f3-40aa-8a04-ff5b1c98a92a
    a=rtcp-mux
    a=rtpmap:111 opus\/48000\/2
    a=rtcp-fb:111 transport-cc
    a=fmtp:111 minptime=10;useinbandfec=1
    a=rtpmap:103 ISAC\/16000
    a=rtpmap:104 ISAC\/32000
    a=rtpmap:9 G722\/8000
    a=rtpmap:102 ILBC\/8000
    a=rtpmap:0 PCMU\/8000
    a=rtpmap:8 PCMA\/8000
    a=rtpmap:106 CN\/32000
    a=rtpmap:105 CN\/16000
    a=rtpmap:13 CN\/8000
    a=rtpmap:110 telephone-event\/48000
    a=rtpmap:112 telephone-event\/32000
    a=rtpmap:113 telephone-event\/16000
    a=rtpmap:126 telephone-event\/8000
    a=ssrc:1962158795 cname:Dnw8e0ynzyRWkTD2
    a=ssrc:1962158795 msid:1286608d-20f3-40aa-8a04-ff5b1c98a92a 1286608d-20f3-40aa-8a04-ff5b1c98a92a
    a=ssrc:1962158795 mslabel:1286608d-20f3-40aa-8a04-ff5b1c98a92a
    a=ssrc:1962158795 label:1286608d-20f3-40aa-8a04-ff5b1c98a92a
    m=application 9 UDP\/DTLS\/SCTP webrtc-datachannel
    c=IN IP4 0.0.0.0
    a=ice-ufrag:0obG
    a=ice-pwd:LvsHqE\/ZlRqnv3Nyq+xUeQHX
    a=ice-options:trickle renomination
    a=fingerprint:sha-256 A1:0E:99:B8:B4:AD:83:47:EB:51:42:32:A9:63:59:4E:07:2A:03:B4:1A:10:04:F6:A7:61:48:6B:51:D1:C6:FE a=setup:actpass
    a=mid:1
    a=sctp-port:5000
    a=max-message-size:262144

     

     

    대충 몇 개 해석을 해보자면,

    7번째 줄에 m=audio 9 UDP\/TLS\/RTP\/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126

    이런 항목이 있는데, 이는 현 기기에서 가지고 있는 오디오 코덱의 종류가 우측 숫자로 표시되어 있고, 선호하는 코덱 순서로 정렬되어 있다.

     

    그리고 이 숫자는 더 아래에 a=rtpmap 항목들을 보면 매핑해볼 수 있는데,

    111은 a=rtpmap:111 opus\/48000\/2 여길 보면, 48000hz 샘플링인 opus 코덱을 의미한다. Opus 코덱은 Voip에서 자주 활용하는 오디오 코덱이기도 하다.

     

    이 SDP를 각 클라이언트가 서로 교환하는 이유는, 음성/영상 미디어 정보를 송수신할 때 각 클라이언트에서 서로 주고받을 수 있는 형태를 맞춰 약속하기 위함이다.

    B 클라이언트가 A 클라이언트에 없는 코덱으로 압축해서 미디어를 보내버리면, A에서는 복호화할 방법이 없어 무용지물이 되기 때문이다.

     

    친구한테 코르크 마개 와인을 선물했는데, 와인따개가 없으면 마시지 못하니까 사전에 와인따개가 있는지 물어보는 것이다. 와인따개가 없으면, 2순위였던 스크류 마개 와인을 선물하면 된다.

     

    ICE 정보 교환

    ICE는 또 뭘까? 당연히 얼음은 아니다.

    Interactive Connectivity Establishment의 약자로, P2P 네트워크에서 STUN, TURN 서버를 활용해 두 클라이언트가 직접 통신하는 가장 짧은 경로를 찾는 과정이다.

     

    ICE 통신 과정은 크게 아래와 같다.

    1. 두 클라이언트간 최단 경로 후보(Ice Candidate)를 전송한다.

    2. 각 클라이언트가 동의한 최단 경로 후보가 있다면, 그것으로 각 클라이언트를 연결한다.

     

    왜 ICE를 활용해야할까?

    NAT나 방화벽 환경 때문에 P2P 연결을 바로 할 수 없는 문제들이 있기 때문이다.

     

     

    인터넷을 사용하려면 고유 IP가 있어야 한다. 하지만 각자가 모두 고유 IP를 가지고 있으면 인터넷 요금도 그만큼 더 내야 한다. 그래서 우리는 하나의 IP를 나눠 쓰기 위해 대부분 NAT를 환경을 활용한다. NAT는 공유기라고 생각하면 편하다.

     

    공유기를 사용하기 때문에 실제 자신의 IP가 무엇인지는 알 수 없다. 컴퓨터는 공유기가 임의로 정해준 번호를 자신의 IP라고 착각하고 사용한다.

    그렇기 때문에 자신의 IP가 무엇인지 알기 위해 STUN 서버가 필요하다.

    NAT환경 때문에 가려진 내 실제 IP가 무엇인지 알려주는 단순한 기능을 하는 서버이다.

     

    naver검색창에 “내 ip”라고 검색하면 실제 IP가 나오는데, STUN 서버는 이것과 매우 유사하다.

     

     

    STUN 프로토콜을 활용하더라도, Symmentric NAT를 사용하는 특수 케이스나, 방화벽 등으로 P2P연결을 할 수 없을 때가 존재하는데, 이럴 때는 TURN 서버를 활용한다.

     

    조금 더 구체적인 시그널링 과정

    코드를 작성할 때 라이브러리에서 제공해 주는 기능들을 활용하면 된다.

    그때 구체적으로 수행해야 하는 것들을 나열해 본다.

    다른 글에서 실제 안드로이드 코드를 보면서 비교해 봐도 좋겠다.

     

    1. 두 클라이언트가 시그널링 서버에 연결한다.
    2. A 클라이언트에서 offer sdp를 만든다 (createOffer)
    3. 만든 offer sdp를 기기에 저장한다 (setLocalDescription)
    4. 만든 offer sdp를 시그널링 서버로 전송한다.
    5. 시그널링 서버는 클라이언트 B에게 A의 offer sdp를 전달한다.
    6. B 클라이언트는 전달받은 offer sdp를 저장한다. (setRemoteDescription)
    7. B 클라이언트는 answer sdp를 만든다. (createAnswer)
    8. 만든 answer sdp를 기기에 저장한다 (setLocalDescription)
    9. 만든 answer sdp를 시그널링 서버로 전송한다.
    10. 시그널링 서버는 클라이언트 A에게 B의 answer sdp를 전달한다.
    11. 클라이언트 A는 전달 받은 answer sdp를 저장한다. (setRemoteDescription)
    12. 두 클라이언트가 시그널링 서버를 통해 통신 최단 거리 후보들을 전송한다. (ICE Candidate)
      1. 교대로 전송하는 것이 아니라 서로 동의할 때까지 지속적으로 전송한다.
    13. 두 클라이언트가 서로 동의한 후보를 찾았다면 두 클라이언트를 연결한다. (ICE Connect)

     

    미디어 서버

    WebRTC로 음성/영상 미디어 데이터를 송수신하는 서비스를 만들다 보면, 자연스럽게 미디어 서버의 존재를 알 수 있다.

    미디어 서버는 왜 사용해야 할까?

     

    WebRTC는 기본적으로 P2P 기반 통신이다.

    그렇기에, 사람 수가 많아지면 많아질수록 미디어 정보를 송수신해야 하는 기기가 많아진다. 그만큼 하나의 기기가 감당해야 하는 연결의 수가 많아진다.

    게다가 여기에 녹음, 음성 및 영상 품질 조절, 잡음조절 등 미디어 프로세싱 작업까지 수행해야 한다면, 그 작은 모바일 프로세서가 얼마나 감당할 수 있을까? 불가능에 가깝다.

     

    미디어 서버는 연결하는 종류에 따라 크게 2가지로 분류할 수 있다.

    각 종류를 간단히 서술해보려 한다.

     

    SFU(Selective Forwarding Unit) 미디어 서버

     

    모든 클라이언트에게 보내던 미디어 스트림을 1개의 미디어 서버에만 보내고, 다른 참여자들의 미디어 스트림은 미디어 서버로부터 각각 받는 형태이다.

    클라이언트와 서버가 부하를 적절히 나눠 가진 형태라고 볼 수 있다.

     

    MCU (Multipoint Control Unit) 미디어 서버

     

    각 클라이언트에서 보낸 미디어 스트림을 서버에서 1개의 미디어 스트림으로 합친 후(Mix), 각 참여자들에게 합친 미디어 스트림 1개를 보내주는 형태이다.

    클라이언트 입장에서는 부담이 굉장히 적어진다는 장점이 있으나, 치명적인 단점을 가진다.

    1. 합쳐진 음성에서 자기 자신의 목소리를 없앨 수 없음. → 즉, 자신의 목소리가 그대로 스트리밍에 반영되어 자신에게 들릴 수 있다.
    2. 모든 미디어를 서버에서 합치는 과정에서 고성능의 서버 하드웨어를 요구한다.

     

    각 연결별 요약을 해주는 좋은 그림 자료가 있어 붙인다.

     

     

    반응형

    댓글

Designed by Tistory.