실시간 네트워킹

실시간 네트워킹 #

왜 실시간 통신에서 네트워킹이 중요한가요? #

네트워크는 실시간 통신의 한계 요소입니다. 이상적으로는 무한 대역폭과 즉시 도착하는 패킷이 있으면 좋겠지만, 현실은 다릅니다. 네트워크는 제한적이며 언제든 조건이 변할 수 있습니다. 네트워크 상태를 측정/관찰하는 일도 어렵습니다. 하드웨어, 소프트웨어, 설정에 따라 행동이 달라질 수 있습니다.

실시간 통신에는 다른 영역에 없는 문제가 있습니다. 웹사이트가 어떤 네트워크에서 좀 느려도, 데이터만 모두 도착하면 사용자는 괜찮습니다. 하지만 WebRTC에서는 데이터가 늦으면 무용지물입니다. 5초 전에 회의에서 한 말을 지금 받는 건 의미가 없습니다. 따라서 실시간 시스템을 만들 때는 타협이 필요합니다. 시간 제한은 얼마이며, 그 안에 얼마나 보낼 수 있을까요?

이 장은 데이터와 미디어 모두에 적용되는 개념을 다룹니다. 이후 장에서는 이론을 넘어서 WebRTC의 미디어/데이터 하위 시스템이 이 문제들을 어떻게 해결하는지 살펴봅니다.

네트워크를 어렵게 만드는 속성은 무엇인가요? #

모든 네트워크에서 잘 동작하는 코드를 만드는 일은 어렵습니다. 많은 요소가 있으며 서로 미묘하게 영향을 주고받습니다. 다음은 흔한 이슈들입니다.

대역폭(Bandwidth) #

대역폭은 경로를 따라 전송할 수 있는 최대 속도입니다. 정적 값이 아니라는 점이 중요합니다. 경로를 사용하는 사람이 늘거나 줄면 달라집니다.

전송 시간과 왕복 시간(RTT) #

전송 시간은 패킷이 목적지에 도착하는 데 걸리는 시간입니다. 대역폭처럼 일정하지 않습니다. 언제든 변동할 수 있습니다.

transmission_time = receive_time - send_time

전송 시간을 계산하려면 송신측과 수신측의 시계를 밀리초 수준으로 동기화해야 합니다. 작은 오차도 신뢰할 수 없는 측정을 만듭니다. WebRTC는 이기종 환경에서 동작하므로 완벽한 동기화에 의존하기 어렵습니다.

이를 우회하는 방법이 왕복 시간(RTT) 측정입니다.

분산 시계 대신, WebRTC 피어가 자체 타임스탬프 sendertime1이 담긴 특수 패킷을 보냅니다. 협력 피어는 이를 받아 타임스탬프를 반사해 돌려줍니다. 원 송신자가 반사된 패킷을 받으면 현재 시각 sendertime2에서 sendertime1을 뺍니다. 이 시간 차이가 RTT입니다.

rtt = sendertime2 - sendertime1

RTT의 절반을 전송 시간의 근사치로 사용합니다. 단, 이 방법은 전송/수신 시간이 대칭이라는 가정을 합니다. 셀룰러 네트워크에서는 대칭이 아닐 수 있습니다. 휴대폰 업로드가 다운로드보다 느린 것을 떠올리면 됩니다.

transmission_time = rtt/2

왕복 시간 측정의 자세한 내용은 RTCP 송신/수신 리포트 절을 참고하세요.

지터(Jitter) #

각 패킷의 전송 시간이 달라질 수 있다는 사실입니다. 지연되다 한꺼번에 도착하는 등 변동이 큽니다.

패킷 손실(Packet Loss) #

전송 중 메시지가 유실되는 것입니다. 꾸준히 손실될 수도, 스파이크로 나타날 수도 있습니다. 위성/와이파이 같은 매체 특성이나, 경로상의 소프트웨어가 원인일 수 있습니다.

최대 전송 단위(MTU) #

단일 패킷의 최대 크기 제한입니다. 하나의 거대한 메시지를 보낼 수 없고, 프로토콜 수준에서 여러 패킷으로 쪼개야 할 수 있습니다. 경로에 따라 MTU도 달라집니다. Path MTU Discovery로 전송 가능한 최대 크기를 파악할 수 있습니다.

혼잡(Congestion) #

네트워크 한계에 도달한 상태입니다. 현재 경로가 처리할 수 있는 최대 대역폭을 넘겼거나, 사업자가 설정한 시간대 제약 등일 수 있습니다.

혼잡의 모습은 다양하며 표준화되어 있지 않습니다. 보통 혼잡 시 초과 패킷을 드롭합니다. 어떤 경우에는 버퍼링이 발생해 전송 시간이 늘어납니다. 혼잡해질수록 지터가 증가할 수도 있습니다. 이 영역은 변화가 빠르며, 혼잡 감지를 위한 새로운 알고리즘이 계속 제안됩니다.

동적(Dynamic) #

네트워크는 매우 동적이며, 조건이 빠르게 바뀝니다. 따라서 측정도 지속적이어야 합니다.

지터 버퍼(Jitter Buffer) #

네트워크로 인한 변동을 흡수하려면 재생 전에 약간 지연을 두고 패킷을 재정렬해야 합니다. 이를 지터 버퍼가 담당합니다.

간단한 예로, 다음과 같은 전송 시간을 관측했다고 합시다.

time=1.00 ms
time=1.45 ms
time=1.73 ms
time=1.80 ms

이 경우 약 1.8ms 정도가 적절합니다. 늦게 도착한 패킷은 지연 창을 소모해 제시간에 재생하도록 하고, 일찍 도착한 패킷은 잠시 보류해 늦은 패킷으로 인해 고갈된 창을 채웁니다. 이렇게 하면 어긋남 없이 부드럽게 전달할 수 있습니다.

지터 버퍼 동작 #

JitterBuffer

모든 패킷은 수신 즉시 지터 버퍼에 추가됩니다. 프레임을 재구성하기 충분한 패킷이 모이면 해당 패킷들이 버퍼에서 방출되어 디코더로 전달됩니다. 디코더는 이를 디코드해 화면에 표시합니다. 버퍼 용량은 한정되어 있으므로, 너무 오래 머무는 패킷은 폐기됩니다.

비디오 프레임이 RTP 패킷으로 바뀌는 과정과 재구성이 필요한 이유는 미디어 통신 장을 참고하세요.

jitterBufferDelay는 네트워크 성능과 재생 매끄러움에 대한 좋은 인사이트를 제공합니다. 이는 수신 스트림과 관련된 WebRTC 통계 API의 일부입니다. 디코딩 전 프레임이 버퍼에서 대기한 시간을 의미하며, 값이 길수록 네트워크 혼잡이 심함을 나타냅니다.

혼잡 감지 #

혼잡을 해결하기 전에 먼저 감지해야 합니다. 혼잡 컨트롤러가 이를 담당하며, 빠르게 발전하는 주제입니다. 높은 수준에서는 모두 비슷하게 동작합니다. 일부 입력을 받아 가용 대역폭을 추정합니다. 예시는 다음과 같습니다.

  • 패킷 손실: 혼잡해질수록 드롭이 늘어납니다.
  • 지터: 장비가 과부하되면 큐잉으로 시간 변동이 커집니다.
  • RTT: 혼잡 시 패킷 도착 시간이 늘어나며, 지터와 달리 계속 증가하는 경향이 있습니다.
  • ECN: 최신 네트워크는 드롭 위험 패킷을 태깅할 수 있습니다.

이 값들은 통화 내내 계속 측정되어야 합니다. 네트워크 사용량이 변하므로 가용 대역폭도 계속 변할 수 있습니다.

혼잡 해결 #

대역폭 추정치를 얻었으면 전송 방식을 조정해야 합니다. 무엇을 보낼지에 따라 방법이 달라집니다.

더 느리게 보내기 #

전송 속도를 제한하는 것이 첫 번째 방법입니다. 혼잡 컨트롤러가 추정치를 제공하면, 송신자가 레이트 리밋을 적용합니다. 대부분의 데이터 통신이 이 방식을 씁니다. TCP 같은 프로토콜에서는 운영체제가 이를 처리하므로 사용자/개발자에게 투명합니다.

더 적게 보내기 #

실시간 미디어처럼 도착 시간에 마감이 있는 경우 느리게 보낼 수 없습니다. 대신 전송 정보를 줄여 제한을 맞출 수 있습니다. 예컨대 사용 가능한 대역폭이 부족하면 비디오 화질을 낮출 수 있습니다. 이를 위해서는 비디오 인코더와 혼잡 컨트롤러 간 긴밀한 피드백 루프가 필요합니다.