-. Web RTC란,Web Real-Time Communication의 약자이며 JS API로 위와 같은 기능들을 제공해주는 오픈소스일뿐이고 우리가 직접 구현해야 한다.
-. Web RTC를 간단히 번역해보자면 웹 실시간 통신이라는 것을 쉽게 알 수 있는데 이 말에서 의미하는 바와 같이 웹, 앱에서 비디오, 마이크 등을 이용해서 실시간 통신을 제공한다는 것이다.
-. Web RTC에서는 우리가 실시간 통신을 하면서 나오는 데이터(비디오에서 나오는 영상 스트림, 마이크에서 나오는 음성 스트림)들을P2P방식으로 Peer 간의 전송이 되도록 지원하고 있다.
Web RTC에서는 다양한 개념들을 다룬다.
이들을 간단히 언급하자면 시그널링(Signaling), ICE(Interactive Connectivity Establishment), STUN(Session Traversal Utilities for NAT), TURN(Traversal Using Relay NAT) 등이 존재한다
[ 시그널링 ]
상대방과P2P연결을 통해 데이터를 상호교환 한다.
하지만 연결을 하고 교환하기 전에 고려해야할 부분은 몇몇 존재 한다.
먼저, 상대방과 연결을 하기 위해서는 상대방의 네트워크 정보가 필요할 것이며 상대방이 보내는 미디어 데이터 정보(해상도, 형식, 코덱 등)가 무엇인지에 대해 알고 전송과 수신 여부에 대해서 알아야할 필요가 있을 것이다.
*******
세션 제어 정보 - 통신의 초기화, 종료, 에러
네트워크 정보 - IP, PORT
미디어 정보 - SDP 형식으로 코덱, 해상도, 송수신 여부를 응답 모델(Offer <-> Answer)을 통해 협상
(SDP(Session Description Protocol)이란, 위에서 언급한 두 개의 Peer 간에 다양한 멀티미디어 컨텐츠의 초기 인수를 설명하기 위한 프로토콜이다.)
*******
그래서 우리는시그널링(Signaling)을 진행한다.
우리는 시그널링 서버를 구축하고 시그널링을 통해 Peer간 위에서 언급한 정보들을 교환한다.
Web RTC에서는 이러한 시그널링에 대해서 어떠한 제한을 두고 있지 않으며 우리가 어떠한 방식으로도 시그널링을 진행할 수 있다.
[ NAT ]
우리는 글로벌 인터넷 세계에서 살아가고 있기에 수많은 IP들이 각각의 컴퓨터들에 할당되어 누구와도 소통할 수 있다.
하지만 우리가 사용하는 IPv4 체계는 전 세계의 사람들을 충당하기에는 너무 부족하다. (2^32 => 4,294,967,296)
IPv6가 나온다면 지금보다 나아질 것이지만 그에 대한 대안으로 단순 사설 IP를 사용하기보다는 공인 IP를 사용하기로 하였다.
이것을 해결해주는 것이 바로NAT(Network Address Traversal)
집에서 각각의 컴퓨터들을 사용하고 핸드폰을 위한 와이파이도 사용하고 다른 스마트 제품들을 위한 인터넷도 공유기를 통해 받는다.
즉, 하나의 공인 IP를 여러 개의 사설 IP로 쪼개 안에서 사용하고 있으면서 외부와 통신할 때는 앞에서 언급한 공인 IP로 통신을 진행하게 된다는 것이다.
하지만 이렇게 되면 외부 IP를 사용해 외부로 나갔다가 다시 결과값이 반환되어 들어올 때 해당 공인 IP를 목적지로 해서 들어올 텐데어떤 사설 IP에서 요청했는지 어떻게 알지?라는 의문을 품을 수도 있는데 NAT는 테이블을 통해 내부 네트워크에 존재하는 사설 IP와 포트 번호를 외부 네트워크와 통신할 때 사용하는 공인 IP와 포트와 매핑하여 저장해놓음으로써 이를 가능하게 해준다.
[ STUN, 홀 펀칭 ]
그렇다면A라는 사람과 B라는 사람이 WebRTC를 이용할 때 A가 B의 공인 IP로 보내면 NAT에서 알아서 B의 사설 IP로 보내주겠지?라고 생각하면 오산이다.
우리에게 아직 문제점이 존재한다.
NAT의 경우, B가 요청을 보내면서 NAT를 거치며 해당 사설 IP 정보와 공인 IP 정보가 매핑되어 테이블에 저장되게 되면 위의 경우는 성립한다.
하지만, 어느 것도 없던 경우 A와 B NAT 테이블에는 어떠한 것도 존재하지 않으므로 각각에 도착할 수 없을 것이다.
이를 위해 존재하는 것이 바로홀 펀칭(Hole Punching)이다.
여기서는 추가적인 서버 S가 존재한다고 하자.
A와 B는 각각 서버 S에 접속하게 되면 NAT를 통해 공인 IP로 변환(Traversal)되어 가므로 S에서는 해당 공인 IP를 알 수 있으며 A와 B가 사설 IP도 알려준다면 사설 IP 정보까지 캐치할 수 있게 된다.
S가 이제 A, B에게 각각의 정보에 대해서 알려준다. 여기까지 된다면, 서버 S의 존재 가치는 여기서 끝이다.
A와 B가 받은 정보를 토대로 각자 진행하면 될 것이다.
[ TURN ]
Full cone NAT
A 서버로 요청을 보내기 위해 한번 [사설 IP/PORT : 공인 IP/PORT] 쌍이 NAT 테이블에 저장되면 항상 그 공인 IP/PORT로의 요청은 해당 사설 IP/PORT로 간다.
B 서버와 통신을 한적이 없는 데도 불구하고 NAT 매핑 정보만 안다면 해당 사설 IP/PORT로 정보 전송이 가능하다.
Address Restrict Cone NAT
Full Cone NAT에서와 달리 기존에 통신하던 서버가 아니라면 불가하다. (위에서 A 서버만 가능, B 불가)
Port Restricted Cone NAT
Address Restrict Cone NAT에서 포트도 본다.
Symmetric NAT
위 세 개와 달리 다른 서버와 통신을 하게 된다면 매핑 정보가 아예 바뀌어 버린다.
여기서 문제가 되는 부분은Symmetric NAT이다.
우리가 기껏 STUN Server를 통해서 사설 IP/PORT와 공인 IP/PORT를 알아왔더니 A, B 각자와 통신을 할때에는 매핑 정보가 아예 바뀌어버려 사용할수도 없게 된다.
이러한 부분을 해결하기 위해 등장한 것이 바로TURN(Traversal Using Relay NAT)이다.
이 부분에 대한 설명은 간단하다.
그냥 단순히 TURN Server과 A, B가 각각 연결을 맺고 이 서버에서 모든 교환 과정을 중계해준다.
[ 결론 ]
이와 같이 우리는 A라는 사용자와 B라는 사용자가 PeerConnection을 맺기 위해 정보를 교환하는 과정에 대해서 알아보았다.
위에서 설명한 과정들 속에서 상대방의 네트워크 정보를 알게 되는데 각각을 사용해서 얻을 수 있는 정보는 다음과 같다.
자신의 사설 IP/PORT
자신의 공인 IP/PORT (By STUN, TURN)
TURN 서버의 IP/PORT (By TURN)
이렇게 상대방과 연결하기 위한최적의 경로를 알기 위한 과정을 제공하는 프레임워크를 바로ICE(Interactive Connectivity Establishment)라고 한다.
상대방의 네트워크 정보와 미디어 정보를 알기 위해 시그널링 과정을 거친다.
네트워크 정보에 대해서 문제점이 발생하는 경우가 빈번히 있기에 이러한 부분을 해결하기 위해 ICE 프레임워크로 최적의 경로를 찾게 된다.
이에 대한 방법으로는 STUN, TURN 서버를 이용하는 방법이 존재한다
Web RTC는 Peer 간에 Peer-To-Peer로 이루어진다고 설명을 했는데 이 방식은 사람의 수가 늘어날 수록 부담이 매우 심해지게 된다.
-. HLS(HTTP 라이브 스트리밍)은 가장 널리 사용되는 비디오스트리밍 프로토콜입니다.
-. HLS는 비디오 파일을 다운로드할 수 있는 HTTP 파일 조각으로 나누고 HTTP프로토콜을 이용하여 전송합니다.
-.클라이언트 장치는 이러한 HTTP 파일을 로드한 후 비디오로 재생합니다.
[ 장점 ]
1. 호환성
HLS는 스마트폰, 태블릿, 노트북 등 다양한 장치에서 스트리밍된 콘텐츠의 소비를 지원합니다.
2. 부드러운 재생
ABR 기능은 HLS를 비디오 스트리밍, 특히 중단할 수 없는 방송 중에 품질을 저하시키더라도 재생되게끔 해줍니다.
3. 비용 효율성
HLS는 HTTP를 기반으로 하며 어떤 장치에서도 확장할 필요 없이 콘텐츠 전송 네트워크를 통해 전달할 수 있으므로 비용 효율적입니다.
4. 보안
HLS는 또한 Flash와 같은 솔루션에 비해 더 안전한 프로토콜입니다.
5. 확장성
HLS는 스트리밍을 확장하여 품질 저하 없이 동시에 전 세계 수백만 명의 시청자를 지원할 수 있습니다.
[ 단점 ]
1. 높은 대기 시간
다른 스트리밍 프로토콜에 비해 HLS는 대기 시간이 더 깁니다
최대 30초 이상의 지연이 생길 수 있음
2. 느린 인터넷 속도
HLS 스트리밍은 지연 시간이 상대적으로 높기 때문에 비디오 게임이나 스포츠 방송과 같이 빠른 라이브 스트리밍이 필요한 사용 사례에는 적합하지 않을 수 있습니다.
[ 첫번째 HLS 재생 목록의 청크 수 설정 ]
일반적으로 스트리밍 서버는 HLS를 사용할 때 재생 전에 충분한 청크를 저장해야 합니다.
이것은 플레이어에 따라 다릅니다.
재생은 일반적으로 플레이어가 3개의 청크가 포함된 첫 번째 HLS 매니페스트를 가져온 후에 시작됩니다.
그러나 일부 플레이어는 3개 미만의 청크 수를 지원합니다.
이러한 상황에서는 재생이 시작되기 전에 첫 번째 매니페스트에서 수신 및 패키징되는 청크 수를 결정하여 지연 시간을 줄이기 위해 이 숫자를 조정할 수 있습니다.
[ 키 프레임 간격 줄이기 ]
GOP(Group of Pictures)라고도 잘 알려진 키프레임 간격은 청크 크기에 영향을 미치는 핵심 요소입니다.
HLS 청크는 키프레임 경계에서 생성되므로 설정한 GOP가 클수록 청크가 커져 라이브 브로드캐스트의 지연 시간이 결정될 수 있습니다.
OBS 및 Wirecast와 같은 인코더를 통해 스트림을 푸시할 때 GOP를 2~3초로 설정하는 것이 좋습니다.
[ 결론 ]
HLS의 장점 중 하나는 모든 인터넷 연결 장치가 HTTP를 지원하기 때문에 전용 서버가 필요한 스트리밍 프로토콜보다 간단하게 실행할 수 있다는 것입니다.
또 다른 장점은 HLS 스트리밍은 재생에 지장을 주지 않고 네트워크 상태에 따라 비디오 품질을 높이거나 낮출 수 있다는 것입니다. 이 때문에 사용자가 비디오를 보는 중에 품질이 나빠지거나 좋아질 수 있습니다. 이 기능은 "적응 비트 전송률 비디오 전송" 또는 "적응 비트 전송률 스트리밍" 이라 알려져 있으며 이 기능이 없으면 네트워크가 느려진 경우 비디오 재생이 완전히 멈출 수 있습니다.
HLS는 Apple이 자사 제품에 사용하기 위해 개발했지만, 현재 다양한 장치에서 사용되고 있습니다.
ex2) IDL 파일을 C#으로 만들때 flayc --csharp -o ./src/main/java/ ./protocol_idl/csGompangProtocol.fbs
컴파일이 성공했을경우 해당폴더에 플랫폼 별 클래스가 생성되어짐.
FlatBuffer의 라이브러리 파일 추가 * 컴파일된 플랫버퍼가 만들어준 Class 도 같이 추가
사용 사용 "순서"에 따라 오류가 날수 있음.
[직렬화 순서] - EchoMsg 기준 - FlatBufferBuilder 생성 - String이 존재한다면 CreateString 으로 문자열을 생성해두고 offset 을 저장(중요) - EchoMsg.StartEchoMsg(); - EchoMsg.AddMsg(); - EchoMsg.EndEchoMsg(fbb); - fbb.Finish(); - fbb.SizedByteArray() => 최종 byte[] 이다. 반드시 SizedByteArray() 를 사용해야하며 fbb에 담긴 메모리를 직접 접근해서 쓰지 않기.
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
var offset = fbb.CreateString(msg);
EchoMsg.StartEchoMsg(fbb);
EchoMsg.AddProtocolId(fbb, (short)1);
EchoMsg.AddMsg(fbb, offset);
var endOffset = EchoMsg.EndEchoMsg(fbb);
fbb.Finish(endOffset.Value);
byte[] packet = fbb.SizedByteArray();
위 소스는 C# 기준.
[역직렬화] - byte[] data = socket.read(); - EchoMsg echoMsg = EchoMsg.getRootAsEchoMsg(data); - echoMsg.Msg(); // String 형태의 Msg를 받을수 있음.
byte[]배열을 getRootAsEchoMsg()에 인자로 넘겨주게 되면, 해당 byte[]에서 원하는 데이터들을 메소드로 접근 가능하다. 이와 같이 데이터 송/수신 시 객체를 만들어서 사용하면 성능좋은 동작을 보장할 수 있다고 한다.
동기화 객체로, 멀티스레드 환경에서 여러 스레드가 동일한 리소스에 동시에 접근하지 못하도록 막아주는 도구입니다. 이를 통해 여러 스레드가 동일한 자원을 동시에 사용하는 경우 발생할 수 있는 데이터 충돌이나 비정상 동작을 방지할 수 있습니다.
주요 특징
상호 배제(Mutual Exclusion): 한 번에 하나의 스레드만 리소스에 접근할 수 있도록 보장합니다.
스레드 안전(Thread Safety): 뮤텍스를 사용하면 다중 스레드 환경에서 데이터 일관성과 무결성을 유지할 수 있습니다.
프로세스 간 동기화: 뮤텍스는 단순히 하나의 프로세스 내에서만 사용되는 것이 아니라, 여러 프로세스 간에도 사용될 수 있습니다. 이는 프로세스 간 자원 접근을 동기화하는 데도 유용합니다.
뮤텍스의 동작 원리
뮤텍스는 **잠금(Lock)과 해제(Unlock)**의 개념을 기반으로 동작합니다. 한 스레드가 뮤텍스를 획득하면(잠금), 다른 스레드는 해당 리소스에 접근하지 못하고 대기하게 됩니다. 뮤텍스를 획득한 스레드가 작업을 끝낸 후 뮤텍스를 해제하면, 대기 중이던 다른 스레드가 뮤텍스를 획득하고 리소스에 접근할 수 있게 됩니다.
뮤텍스와 세마포어 차이
뮤텍스(Mutex): 한 번에 오직 하나의 스레드만 자원에 접근할 수 있습니다.
세마포어(Semaphore): 카운터를 기반으로 동작하여, 여러 스레드가 동시에 자원에 접근할 수 있습니다(최대 N개의 스레드).
요약
**뮤텍스(Mutex)**는 상호 배제를 보장하는 동기화 도구로, 멀티스레드 환경에서 한 스레드가 자원을 사용하고 있을 때 다른 스레드가 접근하지 못하도록 제어합니다.
이를 통해 동시성 문제를 해결하고, 데이터의 일관성과 무결성을 유지할 수 있습니다.
App.xaml 에서의 Mutex 사용 예시
이 코드는 주로 다중 인스턴스 방지를 위해 사용됩니다.
Mutex를 이용해 특정 리소스나 실행 상태를 하나의 인스턴스만 점유할 수 있도록 제한합니다.
이름이 _mutexName인 Mutex가 이미 존재한다면, 이는 다른 인스턴스가 이미 실행 중이라는 뜻이므로 현재 인스턴스를 종료하게 됩니다.
new Mutex(true, _mutexName, out bool createNew):
Mutex 객체를 생성하고, 첫 번째 매개변수로 true를 전달함으로써 즉시 Mutex를 소유하려고 시도합니다.
_mutexName은 이 Mutex의 고유 이름을 지정하는 문자열입니다. 이 이름을 통해 시스템 전체에서 동일한 Mutex를 참조할 수 있습니다.
createNew는 Mutex가 처음 생성되었는지 여부를 반환합니다.
true이면 이 Mutex가 현재 애플리케이션에서 처음 생성된 것이고,
false이면 이미 같은 이름의 Mutex가 존재하는 것입니다(즉, 이미 다른 인스턴스가 실행 중).
if (!createNew):
만약 createNew가 false라면, 이미 동일한 이름의 Mutex가 존재하는 것이므로 다른 인스턴스가 실행 중이라는 의미입니다.