왜 TCP 사고방식을 UDP에 적용해서는 안 되는가
Categories:
- 왜 TCP 사고방식을 UDP에 적용해서는 안 되는가
왜 TCP 사고방식을 UDP에 적용해서는 안 되는가?
구조 차이


TCP는 많은 개념을 가지고 있습니다: 연결 수립, 리소스 사용, 데이터 전송, 신뢰성 있는 전송, 누적 확인에 기반한 재전송, 타임아웃 재전송, 체크섬, 흐름 제어, 혼잡 제어, 최대 세그먼트 크기, 선택 확인, TCP 윈도우 스케일링 옵션, TCP 타임스탬프, 강제 데이터 전달, 연결 종료.
위의 기능들은 UDP에는 기본적으로 없으며, UDP는 데이터링크 계층보다 애플리케이션 계층의 목적지를 구분하는 능력만 약간 더 가집니다. UDP는 충분히 간단하여 매우 유연합니다.
만약 일어날 수 있다면 반드시 일어날 것이다
머피의 법칙:
어떤 일을 하는 방법이 여러 가지 있을 때, 그 중 재앙을 초래하는 방법이 있다면 반드시 누군가는 그렇게 선택할 것이다.
보통 UDP가 게임/음성/영상 등에 적합하다고 소개되며, 소량의 오류 패킷은 서비스에 영향을 주지 않는다고 합니다. 왜 UDP가 이런 시나리오에 적합할까요? UDP가 이런 시나리오에서 사용될 수 있다는 것은 이것이 최적의 해결책이라는 의미는 아닙니다. TCP로는 해결할 수 없는 문제가 있기 때문에 이런 서비스들이 기능이 단순한 UDP 프로토콜을 선택한 것입니다. 소량의 오류 패킷이 서비스에 영향을 주지 않는다는 말은 TCP는 오류 패킷을 신경 쓰고, UDP는 오류 패킷을 신경 쓰지 않으며 실시간성/연속성을 더 중시한다는 의미입니다. UDP의 특징은 TCP가 신경 쓰는 요소들을 신경 쓰지 않는 것이며, 이 요소들이 실시간성에 영향을 미칩니다.
코드 구현 측면에서 UDP는 소켓 하나만 생성하고 포트에 바인딩하면 수신과 송신을 시작할 수 있습니다. 일반적으로 소켓을 사용한 후에는 포트도 사용이 끝납니다.
따라서 저는 이런 식으로 UDP를 사용할 수 있습니다:
- 임의의 IP의 임의 포트로 랜덤 패킷을 보내보고 어느 포트가 응답하는지 확인
- A가 A 포트를 통해 요청 패킷을 B의 B 포트로 전송; B가 C 포트를 통해 응답 패킷을 A의 D 포트로 전송
- A가 A 포트를 통해 요청 패킷을 B의 B 포트로 전송; B가 C에게 위탁하여 C 포트를 통해 응답 패킷을 A의 D 포트로 전송
- A가 A 포트를 통해 요청 패킷을 B의 B 포트로 전송하지만, 송신 패킷의 출발지 IP를 C의 IP로 변경하여 B가 C로 응답 패킷을 전송하게 함
- 양측이 각각 10개의 UDP 포트를 사용하여 동시에 수신과 송신을 진행
이러한 방법들은 TCP에서는 당연히 불가능하지만, UDP 프로토콜에서는 이렇게 할 수 있다면 반드시 누군가 그렇게 할 것입니다. 따라서 TCP의 사고방식을 UDP에 적용하는 것은 이상주의이며, 실제 상황은 우리가 열거할 수 있는 것보다 훨씬 다양합니다.
UDP 패킷은 매우 간단하고 사용도 매우 유연하여 원래는 연결의 개념이 없으며 UDP 연결을 직접 정의해야 합니다. 여러 정의 방법을 시도해봤지만, 모두 정확하게 연결 방향을 판단하는 의도를 완전히 달성할 수는 없었습니다. 이때는 어느 정도의 오류 허용을 받아들여야 합니다. 원래 UDP 연결의 정의가 없었기 때문에 각 당사자들이 UDP 연결에 대해 다른 정의를 내릴 때, 행동이 기대와 다르게 될 것은 불가피합니다.
UDP의 클라이언트 관점
음성/영상 등 서비스는 종종 패킷 손실을 일으키지만, 패킷 손실 방식의 차이가 서비스에 다른 영향을 미칩니다. 예를 들어, 30%의 패킷 손실이 균일하게 발생하는 것과 특정 기간에 모두 손실되는 것의 체험 차이는 명확히 구분됩니다. 명백히, 우리는 더 균일한 패킷 손실을 기대합니다. 그러나 UDP는 흐름 제어를 위한 방법이 없으며, 어떻게 패킷 손실을 유도할지에 대한 방법이 필요합니다. 비록 UDP 통신이 종종 “가능한 한 최선"으로 묘사되지만, 다른 방식의 “최선"은 다른 효과를 가져옵니다.
UDP의 서비스 제공자 관점
TCP 공격의 경우, 클라이언트는 일정한 비용이 들며 연결을 생성하고 유지해야 하므로 공격자는 일정한 대가를 지불해야 합니다. 그러나 UDP 공격에서는 공격자가 지불하는 대가가 훨씬 적습니다. 공격자가 서비스 제공자의 대역폭 트래픽을 소모하는 것을 목표로 한다면 UDP는 좋은 방법입니다. 예를 들어, 서비스가 100GB의 무제한 속도 트래픽을 구매했지만 처리 능력은 초당 10MB이고 수신 속도는 초당 1GB라면, 90%의 요청 트래픽이 무효이지만 이 트래픽은 무료가 아닙니다. 서비스 제공자는 이런 상황을 피해야 합니다.
UDP의 통신사업자 관점
한 번의 통신을 완료하려면 여러 터미널과 통신 채널이 필요하며, 종종 주목받는 것은 서버와 클라이언트뿐입니다. 실제로 통신사업자의 관점도 중요합니다. DDoS 공격에서 우리는 종종 서버 측의 리소스 소비 상황을 걱정하지만, 실제로 통신사업자의 리소스도 제한되어 있습니다. 서버 측이 단순히 요청에 응답하지 않더라도 수신 트래픽은 이미 대역폭을 소모하고 있으며, 다만 이 리소스는 일반적으로 통신사업자에게 속합니다. 우리가 압력 테스트에서 자주 사용하는 “패킷 손실률” 지표는 전체 통신 체인의 패킷 손실을 표현하는 것이지, 단순히 서버 측의 패킷 손실만을 의미하지는 않습니다. 통신사업자도 패킷 손실을 일으킵니다. 통신사업자의 관점에서 보면, 서비스 제공자는 초당 1MB의 대역폭만 구매했지만 클라이언트가 초당 1GB의 속도로 전송한다면, 양측 모두 낭비된 트래픽에 대해 비용을 지불할 필요가 없으며 이 대역폭 비용은 통신사업자가 부담하게 됩니다. 따라서 통신사업자는 이런 트래픽을 차단하려고 노력할 것이며, 이것이 바로 UDP의 QoS입니다. TCP에는 혼잡 제어가 있지만 UDP에서는 통신사업자가 패킷 손실을 통해 트래픽을 제어할 수 있습니다. 실제 상황에서 통신사업자는 더욱 단순하고 직접적인 방법을 사용하여 장시간 사용되는 포트의 트래픽을 직접 차단하는데, 이것이 바로 UDP의 포트 차단입니다. 위챗 통화의 실제 테스트에서 각 통화마다 클라이언트가 여러 포트를 사용하는 것을 발견했으며, 그 중 하나의 UDP 포트가 동일한 서버의 6개 UDP 포트와 통신하는 것으로 추정됩니다. 이는 통신사업자의 포트 차단에 대응하기 위한 것이라고 추정됩니다.
요약
UDP의 유연성은 목표를 달성하는 과정에서 다양한 구현 방법이 존재하며, 모두 합법적이라는 것을 의미합니다. 안정적인 통신을 최종적으로 구현할 수 있다면, TCP와 크게 다르게 구현되더라도 “존재하는 것은 합리적이다"라고 할 수 있습니다. 따라서 우리는 TCP의 개념을 UDP에 완전히 적용해서는 안 됩니다. 제품 설계를 위해 새로운 UDP 연결 정의를 만들어냈다고 하더라도 오류가 발생할 수 있음을 예상하고 허용해야 합니다. 결국 “오류 허용"은 UDP의 핵심 기능이며, 이는 UDP의 장점이며 단점이 아닙니다. 이는 서비스가 능동적으로 선택한 프로토콜의 핵심 역량이며, 어쩔 수 없이 받아들여야 하는 단점이 아닙니다.