← 개인 공부 · Network
STUDY NOTE · 개념 정리

TCP vs UDP 정리: 3-way·4-way 핸드셰이크, 흐름 제어와 혼잡 제어

Network
TCP는 연결을 맺고, 순서와 도착을 보장하는 전송 계층 프로토콜이고, UDP는 연결 없이 데이터그램을 던지기만 한다. TCP는 믿을 수 있는 대신 느리고 무겁고, UDP는 가볍고 빠른 대신 신뢰성은 애플리케이션이 직접 챙겨야 한다.

1. 한눈에 비교

구분TCPUDP
연결연결형 (핸드셰이크 후 전송)비연결형
신뢰성재전송·확인 응답(ACK)으로 보장보장 안 함 (유실 가능)
순서보장 (시퀀스 번호)보장 안 함
데이터 단위바이트 스트림 (경계 없음)데이터그램 (보낸 단위 그대로)
흐름·혼잡 제어있음없음
헤더 크기20~60바이트8바이트
통신 형태1:11:1, 1:N (브로드캐스트·멀티캐스트)
대표 용도HTTP/1.1·2, 이메일, 파일 전송, SSHDNS, 실시간 영상·음성, 게임, QUIC(HTTP/3)

2. 3-way 핸드셰이크 (연결 맺기)

  1. 클라이언트 → 서버: SYN (내 시작 시퀀스 번호는 x)
  2. 서버 → 클라이언트: SYN + ACK (x+1 받을 준비 됐고, 내 시작 번호는 y)
  3. 클라이언트 → 서버: ACK (y+1 받을 준비 됐음) → 연결 성립(ESTABLISHED)

왜 2번이 아니라 3번인가? 양쪽 모두 '내가 보낸 것이 상대에게 닿았다'와 '상대의 시작 번호'를 확인해야 하기 때문이다. 2번이면 서버는 자기 SYN이 클라이언트에 닿았는지 모른다. 또 네트워크에 오래 떠돌던 옛 SYN이 늦게 도착해도, 클라이언트가 3번째 ACK를 보내지 않으니 잘못된 연결이 생기지 않는다.

3. 4-way 핸드셰이크 (연결 끊기)

  1. 클라이언트 → 서버: FIN (나는 더 보낼 게 없음)
  2. 서버 → 클라이언트: ACK (알았음, 하지만 나는 아직 보낼 게 남았을 수 있음)
  3. 서버 → 클라이언트: FIN (나도 다 보냄)
  4. 클라이언트 → 서버: ACK → 클라이언트는 TIME_WAIT에서 잠시 기다렸다 닫음
질문답
왜 4번인가TCP는 양방향이라 각 방향을 따로 닫는다. 서버는 FIN을 받은 뒤에도 남은 데이터를 보낼 수 있어서 ACK와 FIN이 따로 간다 (반 닫힘, half-close)
TIME_WAIT는 왜 있나마지막 ACK가 유실되면 서버가 FIN을 다시 보내는데, 그걸 받아 줄 수 있어야 한다. 또 늦게 도착한 옛 패킷이 같은 포트의 새 연결에 섞이지 않게 한다. 보통 2×MSL(최대 세그먼트 수명) 동안 기다림
TIME_WAIT가 많이 쌓이면연결을 먼저 끊는 쪽에 생긴다. 짧은 연결을 많이 맺는 서버라면 Keep-Alive·커넥션 풀로 연결을 재사용한다

4. 신뢰성: 시퀀스 번호, ACK, 재전송

  1. 보내는 바이트마다 시퀀스 번호를 붙이고, 받는 쪽은 '다음에 받을 번호'를 ACK로 알려 준다.
  2. 정해진 시간(RTO) 안에 ACK가 안 오거나, 같은 ACK가 3번 겹쳐 오면(중복 ACK) 유실로 보고 다시 보낸다(빠른 재전송).
  3. 순서가 뒤바뀐 세그먼트는 받는 쪽 버퍼에서 번호대로 맞춰서 애플리케이션에 넘긴다.

5. 흐름 제어 vs 혼잡 제어

구분흐름 제어 (Flow Control)혼잡 제어 (Congestion Control)
보호 대상받는 쪽 (수신 버퍼가 넘치지 않게)네트워크 (라우터 큐가 넘치지 않게)
판단 기준수신자가 알려 주는 윈도우(rwnd)송신자가 추정하는 혼잡 윈도우(cwnd)
방식슬라이딩 윈도우: ACK 없이 보낼 수 있는 양을 rwnd로 제한느린 시작 → 혼잡 회피, 유실이 보이면 cwnd 줄이기

실제로 보낼 수 있는 양은 min(rwnd, cwnd)이다.

  1. 느린 시작(Slow Start): cwnd를 작게 시작해 ACK마다 늘려서, RTT마다 대략 두 배가 된다.
  2. 혼잡 회피: 임계값(ssthresh)을 넘으면 RTT마다 1 MSS씩 천천히 늘린다(AIMD의 '덧셈 증가').
  3. 유실 감지: 타임아웃이면 cwnd를 처음부터, 중복 ACK 3번이면 절반으로 줄인다(빠른 회복, '곱셈 감소').
  4. 요즘 리눅스 기본은 CUBIC이고, 구글의 BBR은 유실 대신 대역폭과 RTT를 재서 속도를 정한다.

6. UDP는 언제 쓰나

  1. 늦게 오느니 안 오는 게 나은 데이터: 실시간 음성·영상, 게임 위치 동기화. 지난 프레임을 재전송받아 봐야 쓸 데가 없다.
  2. 요청 하나에 응답 하나로 끝나는 짧은 질의: DNS. 핸드셰이크 비용이 질의보다 크다.
  3. 신뢰성을 직접 설계하고 싶을 때: QUIC(HTTP/3)는 UDP 위에서 재전송·암호화·스트림 다중화를 직접 구현해서, TCP의 Head-of-Line 블로킹(앞 패킷 하나가 유실되면 뒤가 전부 대기)을 피한다.
  4. WebRTC 데이터 채널도 '순서 보장 끔 + 재전송 끔'으로 설정하면 UDP처럼 쓸 수 있다.

7. 정리

  1. TCP = 연결 + 순서 + 신뢰성 + 흐름·혼잡 제어, 대신 지연과 오버헤드.
  2. UDP = 헤더 8바이트, 연결 없음, 보장 없음, 대신 빠르고 단순.
  3. 연결은 3번(SYN, SYN-ACK, ACK), 끊기는 4번(양방향을 따로 닫기), 먼저 끊는 쪽에 TIME_WAIT.
  4. 흐름 제어는 받는 사람, 혼잡 제어는 네트워크를 지킨다.
Gunmo Lee
TCP vs UDP 정리: 3-way·4-way 핸드셰이크, 흐름 제어와 혼잡 제어 | Gunmo's Dev Life