순서 보장과 재전송
파일 하나를 전송할 때 TCP는 데이터를 잘게 쪼개 여러 패킷에 나눠 담습니다. 이 패킷들은 인터넷을 통해 각자 다른 경로로 이동할 수 있습니다. 어떤 패킷은 빠른 길로, 어떤 패킷은 혼잡한 길로 갑니다. 그러다 보면 나중에 보낸 패킷이 먼저 도착하거나, 아예 도착하지 못하는 일이 생깁니다. TCP는 이 혼돈 속에서도 데이터를 정확하게, 순서대로 전달합니다. 어떻게 할까요.
순서 번호와 확인 응답
각 패킷에는 순서 번호(Sequence Number)가 붙습니다. "이 데이터는 전체 스트림에서 몇 번째 바이트부터 시작하는 조각이다"라는 표시입니다. 받는 쪽은 패킷을 받으면 확인 응답(ACK, Acknowledgment)을 보냅니다. "몇 번까지 받았다, 다음은 몇 번 보내줘"라는 의미입니다.
예를 들어 클라이언트가 순서 번호 1000부터 시작하는 500바이트 데이터를 보냈다면, 서버는 ACK 번호로 1500을 돌려보냅니다. "1499번까지 받았으니 1500번부터 보내줘"라는 뜻입니다.
슬라이딩 윈도우
패킷 하나 보내고 ACK 받고 다시 하나 보내면 너무 느립니다. 대륙 간 통신에서 왕복 지연이 100ms라면, 초당 겨우 10개밖에 보낼 수 없습니다. 그래서 TCP는 ACK를 기다리지 않고 여러 패킷을 한꺼번에 보냅니다. 이것을 윈도우(window)라 부릅니다.
윈도우 크기만큼의 데이터를 한꺼번에 날리고, ACK가 들어올 때마다 윈도우가 앞으로 움직입니다. 마치 기찻길 위를 미끄러지듯 이동하는 창문처럼 보인다고 해서 슬라이딩 윈도우라 합니다. 이 윈도우가 클수록 한꺼번에 많이 보낼 수 있어 처리량이 높아집니다.
패킷이 사라지면
패킷이 중간에 사라질 수 있습니다. 라우터가 혼잡해 버리거나, 전송 오류가 나거나. 그러면 받는 쪽에서 ACK가 오지 않습니다. 보낸 쪽은 일정 시간을 기다리다 답이 없으면 재전송합니다. 이 대기 시간을 RTO(Retransmission Timeout)라 합니다.
더 빠른 방법도 있습니다. 순서 번호 100이 사라지고 200, 300, 400이 잇따라 도착하면 받는 쪽은 "100은 안 왔고 200을 받았다, 100을 빨리 보내줘"라는 중복 ACK를 세 번 연속 보냅니다. 이 신호를 받은 쪽은 타임아웃을 기다리지 않고 즉시 재전송합니다. 이것이 빠른 재전송(Fast Retransmit)입니다.
흐름 제어 — 상대방이 감당할 만큼만
수신 측의 처리 속도가 송신 측보다 느릴 수 있습니다. 받는 버퍼가 넘치면 패킷을 버려야 합니다. 이를 방지하기 위해 수신 측은 TCP 헤더에 자신이 현재 받을 수 있는 여유 공간, 수신 윈도우 크기를 실어 보냅니다. 송신 측은 이 값을 넘어서 보내지 않습니다.
속도 빠른 서버가 느린 클라이언트에게 데이터를 쏟아붓더라도, 클라이언트가 "나 지금 1000바이트밖에 못 받아"라고 신호를 보내면 서버가 알아서 속도를 줄입니다. 이것이 흐름 제어(Flow Control)입니다.
이러한 순서 번호, ACK, 슬라이딩 윈도우, 재전송의 조합이 TCP 신뢰성의 실체입니다. 다음 절에서는 연결을 끊는 과정과 그 과정에서 등장하는 TIME_WAIT 상태를 살펴봅니다.