네트워크 기초 · TCP 와 UDP · 이론
UDP — 아무것도 약속하지 않아서 얻는 것
한 줄 요약
UDP 는 포트 번호와 체크섬만 얹은 얇은 껍데기이며, 신뢰성을 응용이 직접 설계하고 싶을 때 그 자유를 준다.
왜 이게 필요했나
TCP 의 신뢰성은 공짜가 아니다. 연결 수립에 왕복이 필요하고, 손실이 생기면 재전송이 끝날 때까지 그 뒤 데이터를 응용에 넘겨 주지 않는다. 실시간 음성 통화에서 0.5초 전의 소리를 재전송받아 봐야 쓸모가 없는데도 TCP 는 기다린다. 순서를 보장한다는 약속 때문이다.
이 현상을 헤드 오브 라인 블로킹이라 한다. 어떤 응용에는 신뢰성보다 지연이 중요하고, 그때는 아무것도 약속하지 않는 전송 계층이 오히려 낫다.
어떻게 동작하나
UDP 헤더는 8바이트다. 출발지 포트, 목적지 포트, 길이, 체크섬이 전부다. 연결 상태도, 순서 번호도, 재전송도 없다. 보낸 데이터그램은 도착할 수도 있고 안 할 수도 있으며 순서가 바뀔 수도 있다.
이 단순함이 세 가지를 준다. 첫째, 연결 수립 왕복이 없다. 둘째, 서버가 연결 상태를 유지하지 않으므로 훨씬 많은 클라이언트를 감당한다. 셋째, 응용이 재전송 정책을 직접 정할 수 있다.
DNS 가 UDP 를 쓰는 이유가 첫째와 둘째다. 질의 하나에 응답 하나면 끝나는데 연결을 맺고 끊는 데 왕복 세 번을 쓸 이유가 없다. 다만 응답이 512바이트를 넘으면 서버가 잘림(TC) 플래그를 세우고 클라이언트는 같은 질의를 TCP 로 다시 보낸다. 그래서 DNS 서버로 가는 TCP 53 포트를 막으면 평소에는 멀쩡하다가 레코드가 늘어난 특정 도메인만 해석되지 않는다. 진단하기 어려운 종류의 사고다.
QUIC 은 셋째를 극단까지 밀어붙인 예다. UDP 위에 재전송, 순서 보장, 암호화, 다중화를 전부 새로 구현했다. 왜 TCP 를 고치지 않고 UDP 위에 다시 만들었을까. TCP 는 운영체제 커널과 전 세계의 중간 장비에 박혀 있어 바꾸는 데 십 년이 걸리지만, UDP 위의 구현은 애플리케이션 업데이트만으로 배포되기 때문이다. HTTP/3 가 스트림별로 독립 전달을 제공해 TCP 의 헤드 오브 라인 블로킹을 없앤 것도 이 자유 덕분이다.
현장에서 만나는 모습
UDP 를 쓸 때 반드시 스스로 챙겨야 할 것이 크기다. MSS 클램핑은 TCP 에만 적용되므로 UDP 기반 프로토콜은 경로 MTU 문제를 스스로 감당해야 한다. QUIC 이 기본 데이터그램 크기를 1200바이트라는 보수적인 값으로 잡는 이유가 이것이다.
또 하나. UDP 는 흐름 제어가 없으므로 보내는 쪽이 받는 쪽보다 빠르면 수신 버퍼가 넘쳐 조용히 버려진다. /proc/net/udp 의 drops 열이나 ss -u -a 로 큐 상태를 보면 이 손실을 확인할 수 있다. 메트릭 수집기나 로그 전송기가 "가끔 데이터가 빈다"고 할 때 자주 발견되는 원인이다.
이어지는 퀴즈에서 확인할 것
UDP 를 고르는 것이 언제 합리적인지, TCP 의 순서 보장이 왜 어떤 응용에는 오히려 해로운지 설명할 수 있는지 확인한다.