1. 라이브러리
  2. TCP와 UDP
  3. UDP 심층 분석

업데이트됨 1개월 전

UDP는 손실된 패킷을 복구하지 않습니다. 그게 바로 핵심입니다.

TCP는 패킷 하나가 손실될 때마다 위기로 받아들여, 빈자리가 채워질 때까지 전송을 멈춥니다. 파일을 다운로드할 때는 그게 맞습니다. 하지만 화상 통화에서는 치명적입니다. 500밀리초 전의 영상 프레임은 단순히 늦은 게 아니라 이미 사라진 것입니다. 시청자는 이미 다음으로 넘어갔습니다. 멀티플레이어 게임에서, 0.5초 전에 플레이어가 있었던 위치를 아는 건 지금 어디 있는지 알아야 할 때 아무 도움이 되지 않습니다.

UDP의 철학: 보내고 잊어버린다. 연결 상태도 없고, 추적도 없고, 복구도 없습니다. 덕분에 UDP는 빠르지만, 패킷 손실은 개발자가 직접 해결해야 합니다. 올바른 해결책은 한 가지 질문에 달려 있습니다: 복구가 이루어질 시점에 이 데이터가 여전히 의미 있는가?

시퀀스 번호로 손실 감지하기

손실을 처리하려면 먼저 손실이 발생하고 있다는 사실을 알아야 합니다.

모든 패킷에 시퀀스 번호를 추가하세요—전송할 때마다 증가하는 카운터입니다. 수신 측에서 패킷 1,041 다음에 1,043이 도착하면, 1,042가 사라졌다는 것을 알 수 있습니다. 빈틈이 정확히 얼마나 손실됐는지 알려줍니다.

시퀀스 번호는 중복 패킷(네트워크가 가끔 패킷을 복제함)과 순서 바뀜(1,044보다 1,045가 먼저 도착)도 잡아냅니다. 스트리밍 데이터에서는 네트워크가 전달 순서를 뒤섞더라도 올바른 순서로 재구성할 수 있게 해줍니다.

구현 방법: 패킷 헤더에 32비트 또는 64비트 필드를 추가합니다. 송신 측이 이를 증가시킵니다. 수신 측이 받은 것을 추적합니다. 빈틈이 있으면 손실입니다.

확인 응답으로 선택적 복구하기

일부 UDP 애플리케이션은 TCP에서 빌려오되 실시간 제약에 맞게 조정한 자체 확인 응답 시스템을 구축합니다.

수신 측은 주기적으로 상태 보고를 전송합니다: "패킷 1,040-1,042와 1,044-1,048은 받았는데, 1,043이 없어요." 그러면 송신 측은 1,043을 재전송하는 것이 의미 있는지 결정합니다. 채팅 메시지가 담겨 있다면 그렇습니다. 초당 60프레임 영상 스트림에서 하나의 프레임이 담겨 있다면, 그 순간은 이미 지나갔습니다—건너뜁니다.

TCP와의 차이: 이런 시스템들은 데이터가 무엇을 담고 있는지 이해합니다. 복구가 가치 있는지에 대해 지능적인 판단을 내립니다. 채팅 메시지는 재전송을 위해 200ms를 기다릴 가치가 있습니다. 음성 패킷은 그렇지 않습니다.

이중화로 손실 예방하기

순방향 오류 수정(FEC)은 손실을 기다리지 않습니다. 중복 데이터를 미리 보내서, 수신 측이 별도의 요청 없이 손실된 패킷을 재구성할 수 있게 합니다.

가장 간단한 기법: 패킷 1-4를 XOR 연산으로 결합해 결과를 패킷 5로 보냅니다. 해당 그룹에서 패킷 하나가 사라지면, 나머지 패킷들을 패리티 패킷과 XOR하여 복원합니다. Reed-Solomon 코드와 같은 더 정교한 방식은 한 블록 내에서 여러 개의 손실을 복구할 수 있습니다.

중요한 데이터에는 더 단순한 방법도 있습니다: 두 번 보내는 것입니다. VoIP 애플리케이션은 각 오디오 패킷을 약간의 간격을 두고 두 번 전송할 수 있습니다. 한 복사본이 손실되면, 다른 복사본이 대개 도착합니다. 이 방법은 손실이 무작위적이고 상관관계가 없을 때 효과적입니다. 혼잡한 라우터로 인한 버스트 손실이라면? 별로 도움이 되지 않습니다—두 복사본이 함께 사라질 수 있으니까요.

많은 실시간 애플리케이션은 부분적 이중화 방식을 사용합니다: 현재 데이터와 함께 이전 데이터의 저품질 복사본을 포함시킵니다. VoIP 패킷은 현재 20ms의 고품질 오디오와 이전 20ms의 저품질 오디오를 함께 담습니다. 이전 패킷이 손실됐다면, 백업 데이터가 그 자리를 적절히 채웁니다.

FEC는 단방향 통신이나 지연이 큰 링크에 특히 빛을 발합니다. 위성 방송은 이를 광범위하게 사용합니다—위성 링크를 통한 재전송 요청은 몇 초의 지연을 추가합니다. 단점은 대역폭입니다: 네트워크 상태가 완벽하더라도 추가 데이터를 전송해야 합니다.

예측으로 손실 감추기

여기서 놀라운 점이 있습니다: 연속적인 움직임이나 오디오에서는, 때로는 그냥 만들어내는 것이 최선의 대응입니다.

영상 패킷 100과 102는 도착했지만 101이 손실됐습니다. 보간을 사용합니다—100과 102의 중간 프레임을 생성합니다. 천천히 움직이는 장면에서는 이것이 종종 감지되지 않습니다. 존재한 적 없는 것을 보고 있지만, 알아채지 못합니다.

게임 클라이언트는 항상 예측합니다. 서버가 50ms마다 플레이어 위치를 전송하는데 패킷이 사라지면, 클라이언트는 마지막으로 알려진 위치와 속도를 바탕으로 위치를 추정합니다. 플레이어가 아마도 어디에 있을지 보여줍니다. 다음 업데이트가 도착하면, 오차를 부드럽게 수정합니다. 게임은 짧은 중단 중에도 반응성이 좋게 느껴집니다. 서버가 실제로 보고하지 않은 위치를 보고 있지만, 환상은 유지됩니다.

오디오 애플리케이션은 인접한 오디오를 반복하거나 혼합해 손실된 부분을 합성합니다. 모음 발음 중 20ms의 음성이 손실됐다면? 종종 감지되지 않습니다. 뇌가 알아채지 못합니다.

예측이 효과적인 이유는 현실이 대개 연속적이기 때문입니다. 물체는 순간이동하지 않습니다. 소리는 무작위로 바뀌지 않습니다. 다음 순간은 대개 이전 순간과 비슷합니다. 이를 활용하면 손실이 보이지 않게 됩니다.

전략 선택하기

올바른 접근 방식을 결정하는 세 가지 질문:

데이터가 시간에 얼마나 민감한가? 채팅 메시지는 재전송을 기다릴 수 있습니다. 실시간 영상 프레임은 그럴 수 없습니다.

손실의 영향은 무엇인가? 초당 60프레임 영상에서 한 프레임이 빠지는 건 눈에 띄지 않습니다. "플레이어가 득점했다"는 이벤트가 빠지면 게임 상태가 망가집니다.

각 전략의 비용은 얼마인가? FEC는 항상 대역폭을 소모합니다. 재전송은 지연을 추가합니다. 예측은 연산이 필요하고 연속적인 데이터에만 작동합니다.

실제 애플리케이션은 전략을 혼합합니다:

실시간 영상은 손실을 수용합니다—빠진 프레임은 건너뛰고 계속 재생합니다. 짧은 화질 저하가 재생이 멈추는 것보다 낫습니다.

UDP를 통한 고속 파일 전송은 완벽한 전달이 필요하지만 타임아웃을 기다리는 대신 여러 개의 동시 요청으로 공격적으로 재전송합니다.

멀티플레이어 게임은 플레이어 위치를 확인 응답 없이 스트리밍하지만(어차피 다음 업데이트가 곧 도착하니까), "무기 획득"이나 "점수 획득" 같은 중요 이벤트는 확인 응답과 재전송을 사용합니다. 상태 변화는 추측할 수 없습니다.

VoIP는 기본 보호를 위해 FEC를 사용하고, 짧은 빈틈에는 예측을 사용하며, 큰 빈틈에서는 우아하게 포기합니다—잠깐의 침묵이 지연된 대화보다 낫습니다.

패턴: 데이터를 유용하게 유지하는 가장 단순한 전략을 사용하세요. 신선함이 완전성보다 중요할 때는, 오래된 데이터는 과감히 놓아버리세요.

UDP 패킷 손실에 관한 자주 묻는 질문

인터넷에서 정상적인 패킷 손실은 어느 정도인가요?

일반적인 인터넷 경로에서는 정상적인 조건에서 0.1%에서 2%의 손실이 발생합니다. 혼잡한 네트워크, 불안정한 WiFi, 또는 국제 경로에서는 이보다 높아질 수 있습니다. 잘 설계된 UDP 애플리케이션은 5%의 손실을 무리 없이 처리하고 10-15%까지도 기능을 유지해야 합니다.

여러 전략을 조합할 수 있나요?

네, 그리고 대부분의 실제 애플리케이션이 그렇게 합니다. 영상 스트리밍 앱은 기본 보호를 위해 FEC를, 감지를 위해 시퀀스 번호를, 짧은 빈틈에는 보간을, 키프레임에는 선택적 재전송을 사용할 수 있습니다. 전략들은 서로 보완합니다.

애플리케이션에서 패킷 손실을 어떻게 측정하나요?

보내고 받은 시퀀스 번호를 추적하세요. 특정 시간 창에서 (예상 수신량 - 실제 수신량) / 예상 수신량으로 손실률을 계산합니다. 지속적으로 기록하세요—손실은 하루 중 시간대와 네트워크 경로에 따라 달라집니다.

신뢰성이 필요하다면 그냥 TCP를 쓰면 안 되나요?

TCP의 신뢰성은 헤드 오브 라인 블로킹을 야기합니다: 패킷 50이 손실되면, 51-100번 패킷들이 이미 도착했음에도 기다립니다. 실시간 애플리케이션에서 이는 용납할 수 없는 지연 급증을 만들어냅니다. UDP는 어떤 데이터를 기다릴 가치가 있고 어떤 것은 건너뛰어야 하는지 직접 결정할 수 있게 합니다. 자동 신뢰성을 포기하는 대신, 특정 데이터에서 "신뢰성"이 무엇을 의미하는지 제어권을 얻습니다.

이 페이지가 도움이 되었나요?

😔
🤨
😃
UDP 패킷 손실: 완전성보다 신선함이 중요한 이유 • 라이브러리 • Connected