cd ../
Network·2026-02-11·4 min read·# entry/020

TCP의 결벽증: 패킷 유실을 대하는 우리의 자세 (SACK와 HoL Blocking)

패킷이 중간에 사라지면 네트워크는 어떻게 반응할까? TCP 지연의 주범인 HoL Blocking과 똑똑한 재전송 매커니즘인 Fast Retransmit을 파헤칩니다.

데이터가 하드디스크를 떠나 네트워크를 타는 과정은 순탄치 않습니다. 이번에는 그 여정 중에 발생할 수 있는 **'패킷 유실'**과 그에 대응하는 TCP의 결벽증적인 태도를 분석해 봅니다.

특정 번호의 패킷이 사라졌을 때, TCP는 어떻게 평정심을 유지하며 데이터를 복구할까요?


1. 수신측의 현명한 대응: SACK (Selective ACK)

슬라이딩 윈도우 방식으로 패킷 1번부터 5번까지 연속해서 보냈는데, 하필 3번 패킷만 중간에서 증발하거나 아주 늦게 도착하는 상황을 가정해 봅시다.

1

1. 1, 2번 도착

"1, 2번 잘 받았어. 이제 3번 줘." (ACK 3)

2

2. 4번 도착 (이상 감지)

"어? 3번이 와야 하는데 4번이 왔네?" 수신측은 일단 4번을 버리지 않고 TCP Buffer에 보관합니다. 하지만 서버에게는 여전히 ACK 3을 보냅니다.

3

3. 5번 도착 (재촉)

수신측은 계속해서 3번이 먼저 필요하다고 재촉합니다. 이때 SACK 정보를 실어 보냅니다. "난 아직 3번이 없어서 ACK 3이야. 하지만 **4, 5번(SACK 4-5)**은 이미 잘 챙겨뒀으니까 3번만 빨리 보내!"


2. 지연의 핵심: Head-of-Line (HoL) Blocking

이 상황에서 TCP의 가장 큰 성능 병목 중 하나인 HoL Blocking이 발생합니다.

  • OS 커널의 입장: 수신 버퍼에는 이미 4, 5번이 들어와 있지만, 내 사전에 '순서 위반'은 없다.
  • 프로세스(Web Server) 입장: read() 시스템 콜을 호출해서 데이터를 가져가려고 합니다.
  • TCP의 결벽증: TCP는 순서가 보장된 스트림 서비스입니다. 3번이 도착하기 전에는 4, 5번이 버퍼에 있더라도 절대 프로세스에게 넘겨주지 않습니다.
HoL Blocking의 결과

3번 데이터가 올 때까지 애플리케이션의 read() 호출은 멈춰 있거나(Blocking), 데이터가 없다는 응답을 받으며 대기하게 됩니다. 맨 앞줄(Head-of-Line)이 막혀서 뒤의 멀쩡한 데이터들이 나가지 못하는 현상, 이것이 바로 HoL Blocking입니다.


3. 기다리지 않는다: 빠른 재전송 (Fast Retransmit)

TCP는 3번 패킷이 유실되었다고 판단할 때까지 무작정 타임아웃(Timeout)을 기다리지 않습니다. 여기서 3-Duplicate ACKs라는 규칙이 등장합니다.

  1. 중복 ACK 발생: 수신측이 ACK 3을 중복해서 3번 보냅니다. (서버는 총 4번의 ACK 3을 받음)
  2. 유실 확신: 서버는 "아, 3번이 단순히 늦는 게 아니라 진짜 유실됐구나!"라고 확신합니다.
  3. 즉시 재전송: 타이머가 만료되기 전이라도 서버는 즉시 3번 패킷을 다시 보냅니다.
  4. 합체: 3번이 마침내 도착하면 수신측 커널은 비로소 **"기다리던 3번 왔다! 쌓아둔 4, 5번이랑 합쳐서 한꺼번에 프로세스한테 넘겨주자!"**라고 동작합니다.

4. 왜 하필 '3번'의 중복일까?

왜 중복 ACK가 1번일 때는 가만히 있다가 3번이 되어서야 재전송을 할까요? 여기에는 네트워크의 불확실성을 극복하려는 공학적 타협이 담겨 있습니다.

패킷 뒤바뀜(Out-of-Order) 현상

네트워크는 복잡한 그물망입니다. 3번 패킷은 정체된 경로로 가고, 4번 패킷은 뻥 뚫린 경로로 우회해서 먼저 도착하는 일이 빈번합니다.

  • 중복 ACK 1~2회: 단지 3번 패킷이 4번보다 아주 살짝 늦게 도착하는 것일 수 있습니다. 이때 즉시 재전송하면 네트워크에 동일한 패킷이 2개 돌아다니게 되어 대역폭이 낭비됩니다.
  • 중복 ACK 3회: 통계적으로 3번이나 중복 응답이 올 정도면, 이건 단순한 순서 뒤바뀜이 아니라 진짜 유실일 확률이 압도적으로 높다고 판단하는 임계값입니다.

성급한 재전송의 대가: 혼잡 제어

재전송은 단순히 패킷 하나를 더 보내는 것 이상의 큰 비용을 치릅니다.

성급한 재전송의 위험성
  • 대역폭 낭비: 불필요한 중복 전송은 복잡한 네트워크를 더 복잡하게 만듭니다. * 혼잡 제어 발동: 서버는 패킷 유실을 감지하는 순간 "네트워크가 꽉 막혔구나!"라고 판단하여 전송 속도를 절반으로 뚝 떨어뜨립니다.

단순한 순서 뒤바뀜인데 성급하게 재전송을 결정하면, 서버의 전송 속도가 불필요하게 반토막 나는 대참사가 발생합니다. 그래서 '3번'이라는 신중한 기준을 두는 것입니다.


요약

  • SACK: 빠진 조각이 무엇인지 송신자에게 정확히 알려주는 영리한 피드백입니다.
  • HoL Blocking: 맨 앞 패킷 하나 때문에 뒤의 데이터까지 앱에 전달되지 못하는 TCP의 고질병입니다.
  • Fast Retransmit: 3번의 중복 ACK를 통해 타이머 만료 전 유실을 판단하고 복구하는 매커니즘입니다.