WebRTC를 사용하게 된 이유
화상 공유, 음성 공유가 필요했기때문이다.
WebRTC를 사용하면 웹어플리케이션 및 사이트가 별도의 소프트웨어 없이 웹 브라우저에서 음성, 영상, 미디어 , 텍스트, 파일까지 주고받을수 있다.
WebRTC란
WebRTC는 Web Real-Time Communications의 약자로 웹상에서 실시간 통신이 가능하게 해주는 기술이다!
기본적으로 WebRTC는 P2P통신에 최적화 되어있다.
1:1 통신상황을 그림으로 표현하면 이런 상태인 것이다.
그런데 이렇게 연결하기란 쉬운일이 아니다.
기본 동작
P2P연결은 초대장을 생각하면 이해하기 쉽다.
서로가 서로에게 초대장을 보내고, 연결을 수락하면 P2P연결을 시작한다.
그런데 어떻게 서로에게 초대장을 보낼 수 있을까?
Client A와 Client B는 정말 쌩판 남이다.
초대장을 중계해줄 서버가 필요하다.
보통은 이를 소켓서버로 구현한다.
SDP(초대장)
SDP는 Session Description Protocol의 약자로, P2P연결을 시도하는 피어간의 미디어와 네트워크 정보를 이해하기 위해 사용되는 문자열이다.
offer와 answer형태의 두가지 sdp가 존재하며, 이 두가지를 잘 교환하고 나면 RTP, RTCP프로토콜을 사용해서 P2P연결을 진행한다.
RTCPeerConnection
실제적인 P2P연결은 RTCPeerConnection객체에 의해 일어난다.
해당 객체의 RemoteDescription과 LocalDescription이 설정되면, 통신을 시작한다.
동작순서
A와 B가 서로 통신을 해야하고, A가 이미 socket서버의 방에 입장해있는 상황이라고 가정해보자.
- B가 socket서버에 입장, 방 입장 이벤트 발생
- 서버, B에게 A의 정보 전송
- B, RTCPeerConnection객체와 offer 생성, offer를 LocalDescription으로 설정
- B, 서버에게 offer전송
- 서버, A에게 offer전송
- A, 서버로부터 받은 offer에서 B의정보를 기반으로 RTCPeerConnection 객체 생성
- A, answer생성 후, RemoteDescription으로 설정하고 서버로 answer전송
- B, 서버로부터 받은 answer를 RemoteDescription으로 설정
이렇게 교환한 sdp를 기반으로 각 클라이언트는 연결을 시도한다.
하지만 이것만으로 연결이 되는 것은 아니다.
너의 위치는?
우리는 웹 사이트에 어떻게 접속하는가?
넓디 넓은 인터넷 세상에서 어떻게 특정 사이트로 접속할 수 있을까?
보통은 도메인 네임을 사용하지만, 도메인 네임은 dns서버에 의해 ip주소로 변환된다.
결국은 ip주소로 웹세상에서 접속하는 것이다.
아하! 그럼 상대방의 ip만 알면 접속이 가능하겠군!
하지만 ip라고 다 같은 ip가 아니다. 즉 아무 ip나 다 접속할 수 있는게 아니다.
ip는 공인 ip와 사설 ip가 있다.
공인 IP
IP주소는 임의로 우리가 부여하는게 아니라 전 세계적으로 ICANN이라는 기관이 국가별로 사용할 ip대역을 관리하고, 우리나라의 경우에는 KISA에서 국내 ip주소를 관리하고 있다.
이것을 ISP(Internet Service Provider, KT, LG, SKT등 통신 업체들)가 부여받고, 우리는 위 회사에 가입하여 IP를 제공받아 인터넷을 사용하게 된다. 이때 이렇게 부여받은 IP를 공인 IP라고 한다.
사설IP
집에 다들 와이파이가 되는가? 그렇다면 당신은 거의 100% 공유기를 쓰고 있다.
이처럼 우리가 실제로 사용하는 네트워크 환경에서의 ip는 공인 ip를 직접 사용하는게 아니라 공인 ip를 부여받은 라우터가 ip를 부여해준다. 이를 사설 ip라 한다.
즉 내부적인 네트워크 ip인것이다.
구성을 그려보면 아래와 같다.
따라서 인터넷 환경에서 아무리 A의 PC ip주소인 192.168.0.2에 접속해봤자 A를 찾을수는 없다.
여기서 문제가 생긴다.
공유기를 사용하는 A와 B가 P2P통신이 하고싶다고 가정해보자.
이런 상황인 것이다.
각 PC는 자신의 ip를 192.168.0.14, 192.168.0.13으로 알고있다. 따라서 인터넷 환경에서의 자신의 위치를 정확하게 알지못한다.
ICE (Interactive Connectivity Establishment)
이때 사용되는 것이 ICE 프레임워크다.
ICE는 연결을 위해 가능한 ip주소, 포트번호등을 담은 후보를 교환하고, 이중 가장 좋은 것을 골라 연결한다.
이때, 연결을 위해 필요한 후보를 ICE Candidate라 부른다.
즉, 클라이언트끼리 ICE Candidate를 교환하고, 이중 가장 좋은것을 골라 연결하는 것이다.
ICE Candidate의 교환
ICE Candidate의 교환 역시 교환이 일어날 시점에는 서로가 어디있는지 모르므로, 중계서버인 socket서버를 통해 일어난다.
- A, B ice candidate 후보 모으기
- 다 모았다면 한번에 서버로 전송!
- 각 상대가 받아봄
일반적으로 이렇게 일어나나, 굳이 모아서 보낼 필요가 없으므로 새로운 방법이 도입되었다.
Trickle ICE
기존에 모아서 보내는 방식에서 ICE후보를 찾아내는 즉시 교환하는 형태다.
기본적으로 이 방식으로 교환된다.
하지만 이런 경우는 어떻게 연결할 수 있는걸까?
이때 ICE에서 사용하는 서버가 STUN서버이다.
STUN서버 (Session Traversal Uilities for NAT)
NAT은 Network Address Translation으로, 사설 ip를 공인 ip를 통해 통신할 수 있도록 변환하는 기술이다.
STUN서버는 해당 클라이언트의 공인 ip를 알려준다.
위의 사진의 경우 A가 STUN서버에게 요청을 하면 자신의 로컬주소인 192.168.0.1이 아니라 공인ip주소인 59.33.8.100를 알려주는 것이다.
이렇게 모은 하나의 후보를 ICE Candidate로써 교환하는 것이다. 이러면 이제 B는 A의 위치를 알 수 있게 된다!
이제 제대로 P2P연결을 할 수 있는 것이다!
TURN서버
하지만...하지만 그럼에도 불구하고 네트워크 환경은 다양하다.
앞서말한 사설 ip를 사용하기위해서는 NAT이 필요하다.
NAT은 여러가지 방식이 있는데
간단히 살펴보면
FullCone Nat, Restricted NAT, Symmetric NAT이 있다.
Full Cone NAT
사설 ip/port와 공인 ip/port가 한번 매핑되면 내부 네트워크의 누구나, 어떤 포트던 그 공인 ip/port로 호스트에게 통신을 시도할 수 있다.
Restricted NAT
사설 ip/port와 공인 ip/port가 매핑되면 그 ip주소를 가진 기기라면 어떤 포트던 해당 공인 ip/port로 호스트에게 통신을 시도할 수 있다.
Symmetric NAT
사설 ip/port와 공인 ip/port가 매핑되면 그 ip주소를 가진 기기이고 같은 포트를 가져야만 해당 공인 ip/port로 호스트에게 통신을 시도할 수 있다.
자세한 설명은 이 블로그를 참고하면 좋다.
여기서 Symmetric NAT이 문제다.
한번도 접속하지 않았던 녀석이라면, 접속할 수 있는 방법이 없다.
이건 정말 방법이 없다.
그래서 이러면 P2P연결을 못한다.
그래도 연결을 해야하므로 우회에 사용하는게 TURN 서버다.
이친구는 연결을 P2P로 할 수 없을때, 데이터 전송을 중계해주는 역할을 한다.
이런느낌인 것이다.
그래서 TURN서버를 사용하는 순간 P2P연결이 아니게 돼버린다.
정리
각 미디어 스트림을 교환하기 전까지 일어나는 일련의 단계를 시그널링이라고 한다.
따라서 sdp교환과 ice Candidate교환을 도와주는 서버를 시그널링 서버라고 한다.
- Web RTC는 기본적으로 P2P연결을 통해 일어난다.
- P2P연결을 하려면 sdp교환이 필요한데, offer와 answer의 형태로 교환한다.
- offer와 answer를 통해 RTCPeerConnection객체의 local, remote Description을 설정한다.
- 그와중에 각 클라이언트는 연결에 필요한 후보인 ICE Candidate를 모으고, 모으는 즉시 교환한다.(Trickle ICE의 경우)
- 모든 교환이 완료되면 ICE Candidate 중 가장 좋은 것을 골라 P2P연결을 시도한다. (TURN서버를 쓰는 경우 제외)
- 각 미디어 스트림을 교환한다.
글을 모두 읽었다면 이 글의 gif를 한번 보는걸 추천한다. 굉장히 잘 표현되어있다.
근데 여러명이면 어떻게 하죠?
지금까지 설명은 모두 하나의 클라이언트와 P2P연결을 하는 경우였다.
여러명이면 어떻게 할까?
종류
Mesh방식
각각의 Peer가 모두 P2P연결을 하는 방식이다.
5명인경우 1명이 4명의 stream을 받고, 자신의 stream을 4번 업로드 해야하기때문에 사람이 많아지면 많아질수록 부하가 심해진다.
코드로 구현하는경우 각 클라이언트에서 새로운 연결이 시도될때마다 RTCPeerConnection객체를 만들어서 관리해주면된다.
SFU 방식 (Selective Forwarding Unit)
Selective Forwarding Unit의 약자로
서버가 중계해주어서 자신의 스트림을 한번만 서버로 보내면된다.
다만, 받는 stream은 여전히 4개기때문에 부하가 크다.
MCU 방식 (Multi-point Control Unit)
업로드 하는 스트림도 하나고, 다운로드 하는 스트림도 1개이다.
서버가 연결된 클라이언트를 제외한 모든 클라이언트의 stream을 압축시켜서 보내주기 때문에 가능하다.