에듀테크 프로젝트 대시보드
TCP vs UDP
인터넷의 두 운반책. 하나는 빠짐없이·순서대로 배달하겠다고 약속하고, 다른 하나는 일단 던지고 뒤는 안 돌아본다. 둘 다 IP 위에 얹혀 있지만 성격은 정반대다.
IP는 패킷을 "최선을 다해(best-effort)" 목적지 호스트까지 보내줄 뿐, 도착 여부·순서·중복은 책임지지 않는다. 그 위에서 TCP와 UDP는 포트 번호로 어느 프로그램에 줄지 정하고, 서로 다른 방식으로 IP의 빈틈을 다룬다.
| 항목 | TCP (Transmission Control Protocol) | UDP (User Datagram Protocol) |
|---|---|---|
| 연결 | 3-way handshake로 연결 수립 후 통신 | 연결 없음. 바로 전송 |
| 신뢰성 | ACK + 재전송으로 손실 복구, 100% 도착 보장 | 손실돼도 모름. 재전송 없음 |
| 순서 | 시퀀스 번호로 정렬해 앱에 순서대로 전달 | 도착한 순서 그대로. 뒤바뀔 수 있음 |
| 흐름/혼잡 제어 | 있음 (수신 버퍼·네트워크 상황에 맞춰 속도 조절) | 없음. 앱이 알아서 |
| 헤더 크기 | 20바이트 이상 | 8바이트 |
| 데이터 경계 | 경계 없는 바이트 스트림 | 보낸 단위 = 받는 단위 (데이터그램) |
| 속도/지연 | 핸드셰이크·재전송 대기로 지연이 튈 수 있음 | 오버헤드 최소, 지연이 일정 |
| 대표 사용처 | HTTP(S), 파일 전송, 이메일, SSH | DNS 조회, 실시간 게임, 화상통화(VoIP), 스트리밍, QUIC |
가운데 점선 구간이 믿을 수 없는 네트워크다. 패킷은 무작위로 사라지거나 느리게 도착해 순서가 뒤바뀔 수 있다. 같은 조건에서 두 프로토콜이 어떻게 다르게 행동하는지 보자.
1,2,3… 순서대로만
앱에 넘기고, 먼저 도착한 5는 3,4가 올 때까지 버퍼에 잡아둔다
(Head-of-Line 블로킹).window 크기를 줄여 "천천히 보내"라고 신호한다./tcp-congestion 페이지 참고).UDP는 이 중 아무것도 하지 않는다. 그래서 헤더가 8바이트로 작고, 지연이 예측 가능하며, "조금 깨져도 지금 도착하는 게 중요한" 실시간 응용에 적합하다. 대신 필요하면 애플리케이션이 직접 순서·손실 처리를 구현한다(예: QUIC, 게임 넷코드).
# ── TCP: 연결형 바이트 스트림 ── # 서버 srv = socket(AF_INET, SOCK_STREAM) # STREAM = TCP srv.bind(("0.0.0.0", 9000)); srv.listen() conn, addr = srv.accept() # 3-way handshake 완료까지 대기 data = conn.recv(4096) # 경계 없음 — 여러 send가 붙어 올 수 있음 # 클라이언트 cli = socket(AF_INET, SOCK_STREAM) cli.connect(("host", 9000)) # SYN → SYN-ACK → ACK cli.sendall(b"hello") # 도착·순서는 커널이 보장 # ── UDP: 비연결형 데이터그램 ── # 서버 srv = socket(AF_INET, SOCK_DGRAM) # DGRAM = UDP srv.bind(("0.0.0.0", 9000)) msg, addr = srv.recvfrom(2048) # 한 번에 딱 한 데이터그램 # 클라이언트 cli = socket(AF_INET, SOCK_DGRAM) cli.sendto(b"hello", ("host", 9000)) # connect 없음. 손실돼도 예외 안 남