파일을 다운로드하다가 갑자기 멈춰버린 경험이 있으신가요? 데이터를 보냈는데 상대방이 받았는지 알 수 없다면 TCP는 어떻게 해야 할까요?
TCP는 패킷을 보낸 후 일정 시간 안에 ACK가 오지 않으면 패킷이 손실됐다고 판단하고 재전송합니다. 그렇다면 그 "일정 시간"은 어떻게 결정되는 걸까요?
이 글에서는 TCP가 패킷 손실을 감지하는 방법, 재전송 타이머(RTO)가 어떻게 계산되는지, 그리고 3중복 ACK를 이용한 빠른 재전송(Fast Retransmit)까지 흐름 중심으로 정리해 보겠습니다.
요약
- 재전송 트리거: ACK 미수신(RTO 초과) 또는 중복 ACK 3회(Fast Retransmit)
- RTO란: ACK가 오지 않을 때 재전송을 결정하는 타이머 (Retransmission Timeout)
- 계산 공식: RTO = SRTT + 4 × RTTVAR (RFC 6298)
- 재전송 실패 시: RTO를 2배씩 증가시키는 Exponential Backoff 적용
- SACK: 수신 측이 어떤 패킷을 받았는지 명시해 불필요한 재전송 방지
- 결론: RTO는 고정값이 아니라 네트워크 상태에 따라 계속 변하는 동적인 값
1. 왜 재전송이 필요한가
TCP가 동작하는 IP 네트워크는 본질적으로 패킷 손실이 발생할 수 있는 환경입니다. 라우터 큐 오버플로우, 물리 링크 오류, 네트워크 혼잡 등 다양한 원인으로 패킷이 유실될 수 있습니다.
UDP는 이를 무시하고 그냥 보냅니다. 반면 TCP는 다음 두 가지를 보장해야 합니다.
- 신뢰성: 보낸 데이터가 반드시 목적지에 도착해야 합니다.
- 순서 보장: 패킷이 순서대로 재조합되어야 합니다.
이 두 가지를 보장하는 핵심 메커니즘이 재전송입니다.
2. 패킷 손실을 감지하는 두 가지 방법
방법 1 — RTO 초과 (Retransmission Timeout)
TCP는 패킷을 전송한 뒤 ACK가 오지 않으면 일정 시간 후 재전송합니다. 이 "일정 시간"이 바로 RTO(Retransmission Timeout) 입니다.
송신 측이 패킷 전송
↓
RTO 타이머 시작
↓
타이머 만료 전에 ACK 수신 → 정상
타이머 만료 후에도 ACK 없음 → 재전송
가장 기본적인 감지 방법이지만, RTO는 수백 밀리초에서 수 초 단위이므로 손실 감지까지 시간이 걸립니다. 이 점이 아래 Fast Retransmit 방식에 비해 복구 속도가 느린 이유입니다.
방법 2 — 중복 ACK & Fast Retransmit
수신 측은 순서가 어긋난 패킷이 오면, 마지막으로 정상 수신한 번호의 ACK를 반복해서 보냅니다. 송신 측이 동일한 ACK를 3번 받으면(3 Duplicate ACK) 패킷 손실로 판단하고 RTO를 기다리지 않고 즉시 재전송합니다.
패킷 1, 2, 3, 4, 5 전송 / 패킷 3이 손실됨
↓
수신 측: 패킷 2까지 받음 → ACK=3 전송
수신 측: 패킷 4 도착 (순서 어긋남) → ACK=3 재전송 (Duplicate ACK 1)
수신 측: 패킷 5 도착 (순서 어긋남) → ACK=3 재전송 (Duplicate ACK 2)
↓
송신 측: ACK=3이 3번 중복 수신
↓
RTO를 기다리지 않고 즉시 패킷 3 재전송 (Fast Retransmit)
RTO 방식보다 훨씬 빠르게 복구되며, Linux, macOS, Windows 모두 기본 활성화되어 있습니다.
3. RTO는 어떻게 계산되는가
RTO가 너무 짧으면 멀쩡한 패킷을 재전송하고, 너무 길면 손실 복구가 늦습니다. TCP는 RTT(Round-Trip Time) 를 측정해 RTO를 동적으로 계산합니다 (RFC 6298).
RTT 측정
RTT = ACK 수신 시각 - 패킷 전송 시각

RTT는 네트워크 혼잡도, 라우팅 경로, 서버 처리 속도에 따라 매 패킷마다 달라집니다. 단일 RTT 측정값을 그대로 RTO로 사용하면 네트워크가 일시적으로 느려졌을 때 불필요한 재전송이 폭발적으로 발생할 수 있습니다. 이를 위해 RFC 6298은 SRTT와 RTTVAR 두 값을 도입해 RTT를 평활화(smoothing)합니다. 각 값의 계산 방식은 다음과 같습니다.
SRTT와 RTTVAR 계산
TCP는 RTT의 평균(SRTT)과 변동폭(RTTVAR)을 지수 가중 이동평균(EWMA)으로 추적합니다.
SRTT (Smoothed RTT) — 평활화된 RTT
SRTT = (1 - α) × SRTT + α × RTT_sample (α = 0.125)
새로 측정한 RTT가 전체의 12.5%만 반영되고, 기존 평균이 87.5% 유지됩니다. 네트워크가 일시적으로 느려져도 SRTT가 급격히 올라가지 않습니다.
RTTVAR (RTT Variation) — RTT 변동폭
RTTVAR = (1 - β) × RTTVAR + β × |SRTT - RTT_sample| (β = 0.25)
RTT가 얼마나 불규칙하게 변하는지를 측정합니다. 변동이 클수록 RTO에 여유를 더 줍니다.
최종 RTO 계산
RTO = SRTT + 4 × RTTVAR
RTTVAR에 4를 곱하는 이유는 대부분의 RTT가 SRTT±2σ 범위 안에 들어오기 때문입니다. 4를 곱하면 약 95% 이상의 RTT 변동을 커버해 불필요한 재전송을 최소화합니다.
예시 계산
측정 RTT_sample = 100ms
초기값: SRTT = 100ms, RTTVAR = 50ms
SRTT = (1 - 0.125) × 100 + 0.125 × 100 = 100ms
RTTVAR = (1 - 0.25) × 50 + 0.25 × |100 - 100| = 37.5ms
RTO = 100 + 4 × 37.5 = 250ms
주의: RFC 6298은 RTO의 최솟값을 1초로 권장합니다. 계산된 RTO가 1초 미만이어도 최소 1초를 유지합니다. Linux 커널에서는 이 값을 200ms까지 낮출 수 있도록 구현되어 있습니다.
4. 재전송 실패 시 — Exponential Backoff
RTO 시간이 지나도 ACK가 오지 않아 재전송을 했는데, 그 재전송도 실패하면 어떻게 될까요? TCP는 Exponential Backoff(지수 백오프) 를 적용합니다. 재전송이 실패할 때마다 RTO를 2배씩 증가시킵니다.
1차 재전송 실패 → RTO × 2
2차 재전송 실패 → RTO × 4
3차 재전송 실패 → RTO × 8
...
최대 재전송 횟수 초과 → 연결 종료

이 방식의 핵심은 네트워크 혼잡을 악화시키지 않는 것입니다. 패킷이 계속 손실된다는 것은 네트워크가 혼잡하다는 신호입니다. 이 상황에서 재전송을 빠르게 반복하면 혼잡이 더 심해집니다. RTO를 늘려 재전송 빈도를 줄임으로써 네트워크가 회복할 시간을 줍니다.
Linux 기준으로 최대 재전송 횟수는 기본값 15회입니다.
# 최대 재전송 횟수 확인 (Linux)
cat /proc/sys/net/ipv4/tcp_retries2
5. SACK — 더 정밀한 재전송
기본 TCP는 손실된 패킷 이후의 모든 패킷을 다시 보내야 할 수 있습니다. 이를 개선한 것이 SACK(Selective Acknowledgment) 입니다 (RFC 2018).
패킷 1, 2, 3, 4, 5 전송 / 패킷 2, 3이 손실됨
기본 TCP:
수신 측 → ACK=2 (1만 받음)
송신 측 → 2, 3, 4, 5 전부 재전송 (비효율)
SACK 사용 시:
수신 측 → ACK=2, SACK={4, 5} (4, 5는 받았음을 명시)
송신 측 → 2, 3만 재전송 (정밀 복구)
수신 측이 "어떤 패킷을 받았는지"를 TCP 옵션 필드에 명시합니다. 송신 측은 실제로 손실된 패킷만 골라서 재전송할 수 있어 대역폭 낭비가 줄어듭니다. Linux 2.4 이상, macOS, Windows 모두 기본 활성화되어 있으며, RFC 2018 기준 표준 구현입니다.
6. RTO 계산 비교표
| 항목 | 설명 | RFC 6298 기본값 |
|---|---|---|
| RTT_sample | 실제 측정한 왕복 시간 | 매 패킷마다 측정 |
| SRTT | 평활화된 RTT 평균 | α = 0.125 |
| RTTVAR | RTT 변동폭 | β = 0.25 |
| RTO | 재전송 타이머 | SRTT + 4 × RTTVAR |
| RTO 최솟값 | 너무 짧은 RTO 방지 | 1초 (Linux는 200ms) |
| Exponential Backoff | 재전송 실패 시 RTO 증가 | 2배씩 증가 |
추가 팁
첫 번째 패킷은 RTO를 어떻게 설정하는가
- 연결 초기에는 RTT를 측정한 적이 없기 때문에 SRTT와 RTTVAR가 없습니다. RFC 6298은 이 경우 초기 RTO를 1초로 설정하도록 권장합니다. 첫 번째 SYN 패킷의 RTO가 1초인 이유입니다.
Karn's Algorithm
- 재전송된 패킷의 ACK로는 RTT를 측정하지 않습니다. 재전송 패킷의 ACK가 원본에 대한 응답인지, 재전송에 대한 응답인지 알 수 없기 때문입니다. 이를 Karn's Algorithm이라고 하며, 부정확한 RTT 측정으로 인한 RTO 왜곡을 방지합니다.
Timestamp 옵션 (RFC 7323)
- TCP Timestamp 옵션을 사용하면 재전송 패킷에서도 정확한 RTT를 측정할 수 있습니다. Karn's Algorithm의 한계를 보완하며, 현재 대부분의 OS에서 기본 활성화되어 있습니다.
실무에서 RTO가 중요한 이유
- 서버 간 통신 지연이 갑자기 길어지는 현상이 발생했을 때, 네트워크 패킷 손실로 인한 RTO 증가가 원인일 수 있습니다. 단순히 서버가 느린 것처럼 보이지만 실제로는 TCP 재전송이 반복되며 RTO가 수 초까지 늘어난 경우입니다. RTO 동작 원리를 이해하고 있으면 원인 파악이 훨씬 빠릅니다.
📌 정리
- TCP는 RTO 초과 또는 3 Duplicate ACK(Fast Retransmit)로 패킷 손실을 감지합니다.
- RTO는 RTT 측정값을 기반으로 SRTT + 4×RTTVAR 공식으로 동적 계산됩니다.
- 재전송 실패 시 지수 백오프로 RTO를 2배씩 늘려 네트워크 혼잡을 완화합니다.
- SACK를 사용하면 손실된 패킷만 정밀하게 재전송해 대역폭 낭비를 줄입니다.
📌 실무에서 중요한 이유
- RTT가 높은 환경에서 패킷 손실은 수백 ms 지연으로 직결됩니다.
- 로드밸런서 idle timeout은 TCP RTO보다 길게 설정해야 재전송 중 연결 강제 종료를 방지합니다.
- SACK 활성화 여부와
tcp_retries2설정은 고트래픽 서버 튜닝의 기본 항목입니다. - Timestamp 옵션 활성화로 더 정확한 RTT 측정이 가능합니다.
참고 자료
- RFC 6298 - Computing TCP's Retransmission Timer
- RFC 793 - Transmission Control Protocol
- RFC 2018 - TCP Selective Acknowledgment Options
- RFC 7323 - TCP Extensions for High Performance
'cs 기초 > 네트워크' 카테고리의 다른 글
| [네트워크] TCP 속도는 왜 느려질까? (흐름 제어와 혼잡 제어) (0) | 2026.05.18 |
|---|---|
| [네트워크] TCP 연결은 어떻게 시작되고 종료될까? (Handshake) (0) | 2026.05.14 |
| [네트워크] IP 주소와 MAC 주소: 왜 두 가지 주소가 필요한가? (0) | 2026.04.27 |
| [네트워크] TCP와 UDP: 어떻게 다르고, 언제 선택해야 하는가? (0) | 2024.06.12 |
| [네트워크] ARP 프로토콜: 어떻게 동작하고, 왜 위험한가? (0) | 2024.06.12 |