UDP — 가볍게, 빠르게, 책임은 앱이
TCP는 신뢰성을 위해 핸드셰이크·순서번호·재전송·흐름/혼잡 제어라는 많은 절차와 상태를 짊어졌다. 그런데 그 모든 게 항상 필요할까? 화상 통화를 떠올려 보자 — 0.2초 전의 음성 한 조각이 길에서 사라졌다면, 그걸 재전송받아 뒤늦게 트는 것보다 그냥 버리고 지금 음성을 트는 게 낫다. 여기서는 신뢰성보다 지연이 중요하다. 이런 경우를 위한 가벼운 전송 계층이 UDP다.
UDP가 하는 일 — 사실 거의 안 한다
UDP는 IP의 best-effort를 거의 그대로 위층에 노출한다. 헤더라곤 출발/목적 포트, 길이, 체크섬이 전부다.
핸드셰이크가 없고(보내고 싶을 때 그냥 보낸다), 순서 보장이 없고, 재전송이 없고, 흐름·혼잡 제어가 없다. UDP가 더해 주는 건 사실상 포트(어느 프로그램에게 줄지)와 체크섬(깨졌는지 정도만 확인) 둘뿐이다. 그래서 빠르고 가볍다 — 연결 상태를 기억할 필요가 없으니 서버가 수많은 클라이언트를 가뿐히 상대하고, 첫 패킷부터 왕복 지연 없이 바로 나간다.
그래서 무엇이 다른가 — TCP vs UDP
| TCP | UDP | |
|---|---|---|
| 연결 | 핸드셰이크로 수립 | 없음(그냥 보냄) |
| 신뢰성 | 재전송·순서·중복 제거 | 없음(빠지면 그만) |
| 제어 | 흐름·혼잡 제어 | 없음 |
| 무게 | 상태·절차 많음 | 가벼움·빠름 |
| 적합 | 정확성이 중요(웹·파일·DB) | 지연이 중요(통화·게임·DNS) |
선택 기준은 한 줄이다 — 한 바이트도 틀리면 안 되는가(TCP), 아니면 늦느니 차라리 빠지는 게 나은가(UDP). 웹페이지·파일 전송·DB는 TCP, 실시간 음성·영상·온라인 게임은 UDP가 어울린다. DNS도 (짧은 질의·응답이라) 기본은 UDP를 쓴다(다음 편).
신뢰성이 필요하면? 앱이 골라서 얹는다
흥미로운 건 — UDP를 쓴다고 신뢰성을 영영 포기하는 게 아니라, 필요한 만큼만 애플리케이션이 직접 얹을 수 있다는 점이다. 게임은 "캐릭터 위치는 좀 빠져도 되지만(최신만 중요), 아이템 획득은 반드시 도착해야 한다"처럼 — 메시지마다 신뢰 수준을 다르게 설계한다. 이 발상을 표준으로 끌어올린 게 QUIC다. UDP 위에 신뢰성·순서·혼잡 제어·*암호화(TLS)*까지 얹되, TCP의 약점(연결마다 핸드셰이크 RTT, 한 스트림이 막히면 다 막히는 head-of-line 블로킹)을 개선했다 — HTTP/3가 바로 이 QUIC 위에서 돈다(HTTP 편에서 다시).
실무에서는 — "왜 게임/통화는 끊겨도 멈추진 않을까"의 답이 UDP다. 재전송으로 멈추기보다 빠진 채 진행하는 설계다. 반대로 DNS가 가끔 TCP로 떨어지는 경우도 있는데(응답이 UDP 한 패킷에 안 담길 만큼 클 때), 이는 "기본은 가볍게(UDP), 필요하면 무겁게(TCP)"의 전형이다. 그리고 방화벽·NAT가 UDP를 까다롭게 다루기도 해(상태가 없어 매핑이 빨리 만료), 실시간 서비스는 keepalive 패킷으로 매핑을 살려 두기도 한다.
정리하면, UDP는 IP의 best-effort를 거의 그대로 노출하는 가벼운 전송 계층이다 — 포트와 체크섬만 더하고, 핸드셰이크·재전송·제어는 없다. 그래서 빠르고 가벼워 지연이 중요한 실시간(통화·게임·DNS)에 어울린다. 신뢰성이 필요하면 앱이 필요한 만큼 직접 얹고, 그걸 표준화한 QUIC가 HTTP/3의 토대가 된다. 정확성이 중요하면 TCP, 지연이 중요하면 UDP — 전송 계층의 두 갈래다.