আপডেট হয়েছে ১ মাস আগে
TCP는 네트워크를 믿지 않습니다. 믿을 여유가 없습니다.
모든 패킷에는 암묵적인 질문이 담겨 있습니다: 이거 받았어요? 수신 측은 확인 응답으로 대답합니다. 그 응답이 끊기거나 잘못 돌아오면, TCP는 최악을 가정하고 데이터를 다시 보냅니다. 이 끊임없는 의심이 바로 신뢰성의 대가입니다.
TCP가 문제를 감지하는 방법
TCP는 시퀀스 번호와 확인 응답(ACK)을 사용해 전송 중인 모든 바이트를 추적합니다. 송신 측은 각 세그먼트에 번호를 붙이고, 수신 측은 다음에 기대하는 바이트를 나타내는 ACK로 응답합니다. 이렇게 피드백 루프가 만들어집니다: 전송, 확인, 추가 전송.
피드백이 끊기면 TCP가 알아챕니다. 두 가지 신호가 있습니다:
타임아웃. 송신 측은 ACK를 기다립니다. 계산된 시간 안에 ACK가 오지 않으면, TCP는 세그먼트가 손실됐다고 가정하고 재전송합니다.
중복 ACK. 수신 측이 순서가 뒤바뀐 세그먼트를 받습니다 — 예를 들어 1, 2, 3번 세그먼트를 받은 후 5번이 오는 경우. 4번이 없습니다. ACK는 누적 방식이기 때문에 (특정 시퀀스 번호까지 받았음을 확인하는 방식), 수신 측은 5번 세그먼트를 확인할 수 없습니다. 그래서 3번에 대한 ACK를 다시 보냅니다. 6번이 도착하면 또 보냅니다. 순서가 맞지 않는 세그먼트가 올 때마다 중복 ACK가 발생합니다.
TCP는 네트워크가 문제를 알려줄 때까지 기다리지 않습니다. 패턴에서 손실을 추론합니다 — 확인 응답이 와야 할 곳의 침묵, 진전이 있어야 할 곳의 반복.
재전송 타임아웃 (RTO)
재전송 타임아웃(RTO)은 TCP가 세그먼트가 손실됐다고 판단하기 전에 얼마나 기다릴지를 결정합니다.
너무 짧으면: TCP가 불필요하게 재전송하여 대역폭을 낭비하고 혼잡을 악화시킵니다.
너무 길면: 패킷이 실제로 손실됐을 때 애플리케이션이 멈춥니다.
TCP는 측정된 왕복 시간(RTT) — 세그먼트가 목적지에 도달하고 ACK가 돌아오는 시간 — 을 바탕으로 RTO를 동적으로 계산합니다. 하지만 RTT는 끊임없이 변합니다. 혼잡, 라우팅 변경, 처리 지연이 모두 영향을 미칩니다.
이 변동성을 처리하기 위해, TCP는 최근 측정값을 평균 낸 평활화된 RTT(SRTT)와 변동을 추적하는 RTT 분산(RTTVAR)을 유지합니다. RFC 62981의 RTO 공식:
이 공식은 의도적으로 보수적입니다 — 일반적으로 평균 RTT보다 몇 배 길어서, 정상적인 지연 변동을 손실로 오인하는 것을 방지합니다.
타임아웃이 발동하면, TCP는 단순히 재전송하는 것에 그치지 않고 이후 시도에서 RTO를 두 배로 늘립니다. 이 지수 백오프(exponential backoff)는 혼잡 가능성이 있는 네트워크의 부하를 줄여줍니다. 여러 번의 재전송이 실패하면, TCP는 결국 포기하고 애플리케이션에 오류를 보고합니다.
빠른 재전송: 기다리지 않고 판단하기
타임아웃을 기다리는 것은 느립니다. RTT가 50ms이지만 RTO가 200ms인 연결에서, 타임아웃 기반 복구는 필요한 것보다 네 배나 더 걸립니다.
송신 측이 같은 시퀀스 번호에 대한 중복 ACK를 세 번 받으면 — 총 네 개의 동일한 ACK — 타임아웃을 기다리지 않고 즉시 재전송합니다.
왜 세 번일까요? ACK 하나만 중복되는 건 패킷이 순서 없이 도착한 것일 수 있습니다. 두 번도 여전히 순서 재배열일 수 있습니다. 하지만 중복 ACK 세 번 — 수신 측이 같은 것을 계속 요청하는 상황 — 은 무언가가 진짜로 빠졌다는 TCP의 신호입니다.
이 "세 번의 중복 ACK" 규칙은 전체 타임아웃 기간을 기다리는 대신 약 한 번의 RTT 내에 손실을 복구합니다.
선택적 확인 응답 (SACK)
표준 TCP 확인 응답은 누적 방식입니다: "1000번 바이트까지 모두 받았습니다." 세그먼트 하나가 손실됐을 때는 잘 작동합니다. 하지만 같은 윈도우에서 여러 세그먼트가 손실되면, 송신 측은 무언가가 빠졌다는 건 알지만 정확히 무엇인지는 모릅니다.
RFC 20182에서 정의된 선택적 확인 응답(SACK)이 이 문제를 해결합니다. SACK가 활성화되면, 수신 측은 이렇게 보고합니다: "11000 바이트와 20013000 바이트를 받았는데, 1001~2000 바이트가 없습니다."
이제 송신 측은 정확히 어떤 세그먼트를 재전송해야 하는지 압니다. SACK 없이는 첫 번째 손실부터 그 이후 모든 것을 재전송할 수도 있습니다. SACK를 사용하면 실제로 없는 것만 재전송합니다.
SACK는 연결 설정 중에 협상됩니다 — 양쪽 모두 지원해야 합니다. 최신 운영체제는 기본으로 활성화되어 있습니다. 여러 세그먼트가 동시에 전송 중일 수 있는 고대역폭, 고지연 연결에서 특히 유용합니다.
재전송의 비용
모든 재전송은 낭비입니다 — 네트워크는 그 데이터를 두 번 운반했고, 애플리케이션은 한 번만 필요했습니다.
최선의 경우: 빠른 재전송이 작동하여, 추가로 한 번의 RTT만큼 지연이 발생합니다.
최악의 경우: 지수 백오프가 적용된 타임아웃 기반 재전송이 패킷 한 개 손실을 수 초의 지연으로 만듭니다.
재전송은 혼잡 제어도 유발합니다. 타임아웃은 TCP에게 네트워크가 과부하 상태라고 알리고, TCP는 전송 속도를 급격히 줄입니다 — 때로는 90% 이상. 다시 속도를 높이는 데 시간이 걸립니다. 빠른 재전송은 더 부드럽지만 (속도를 초기화하는 대신 절반으로 줄임), 그래도 처리량에 영향을 줍니다.
건강한 네트워크의 재전송 비율은 1% 미만입니다. 3~5% 이상이면 문제를 나타냅니다: 혼잡, 결함 있는 하드웨어, 무선 간섭, 라우팅 문제. 대화형 트래픽(SSH, 게임)은 지연 증가의 영향을 받습니다. 대량 전송은 처리량 감소의 영향을 받습니다.
재전송 문제 진단
재전송 비율이 높아지면, 패턴을 살펴보세요.
지속적인 낮은 재전송 비율은 고질적인 하드웨어 문제를 시사합니다: duplex 불일치, 손상된 케이블, 불안정한 무선 신호.
버스트성 재전송은 트래픽 부하에 따라 나타났다 사라지는 혼잡이나 간섭을 가리킵니다.
패킷 캡처(tcpdump, Wireshark)가 구체적인 내용을 드러냅니다. 같은 세그먼트가 여러 번 재전송됩니까? 심각한 손실입니다. 재전송이 다양한 시퀀스 번호에 걸쳐 산재해 있습니까? 무작위 손실입니다. 트래픽 급증과 상관관계가 있습니까? 혼잡입니다.
시스템 통계도 도움이 됩니다. Linux에서 netstat -s는 총 재전송 카운터를 보여줍니다. 시간에 따라 추적하면 문제가 언제 시작됐는지, 그리고 설정 변경, 트래픽 패턴 변화, 하드웨어 교체 같은 변화와 상관관계가 있는지 알 수 있습니다.
흔한 원인들: 버퍼 블로트(과도한 버퍼링으로 인한 타임아웃), 적절한 큐 관리 없는 혼잡, 무선 간섭, 결함 있는 NIC, 예측 불가능하게 패킷을 버리는 미들박스. 데이터 센터에서는 ACK가 데이터와 다른 경로를 취하는 비대칭 라우팅을 주의하세요 — 불필요한 재전송을 유발할 수 있습니다.
TCP 재전송에 대한 자주 묻는 질문
TCP는 왜 하나가 아니라 세 번의 중복 ACK를 기다리나요?
패킷은 손실 없이 순서가 뒤바뀌어 도착하기도 합니다 — 라우터가 다른 경로로 보낼 수 있거든요. ACK 하나의 중복은 단순한 순서 재배열일 수 있습니다. 세 번의 중복 ACK는 수신 측이 이미 이후의 여러 세그먼트를 받았음에도 여전히 같은 것을 기다리고 있다는 뜻입니다. 그 시점에서 순서 재배열 가능성은 낮고 손실이 거의 확실합니다.
재전송과 불필요한 재전송의 차이는 무엇인가요?
재전송은 실제로 손실된 데이터를 다시 보내는 것입니다. 불필요한 재전송(spurious retransmission)은 손실되지 않은 데이터를 다시 보내는 것입니다 — ACK가 단지 지연됐을 뿐입니다. 불필요한 재전송은 대역폭을 낭비하고 필요 없는 혼잡 제어를 유발합니다. RTT 변동성이 높으면 지연된 ACK가 도착하기 전에 타임아웃이 발동되어 불필요한 재전송이 늘어납니다.
TCP 재전송 동작을 조정할 수 있나요?
네, 하지만 신중하게 해야 합니다. Linux는 TCP가 포기하기 전에 몇 번 재전송할지 제어하는 tcp_retries1과 tcp_retries2 같은 파라미터를 제공합니다. 이 값을 낮추면 네트워크가 끊겼을 때 연결이 더 빨리 실패합니다. 높이면 연결이 더 오래 유지되지만 오류 감지가 지연됩니다. 기본값은 대부분의 시나리오에서 잘 작동합니다.
패킷 손실은 동영상 스트리밍에 어떤 영향을 미치나요?
프로토콜에 따라 다릅니다. TCP 기반 스트리밍(일부 HTTPS 동영상 등)은 재전송이 완료되는 동안 일시 정지됩니다. UDP 기반 스트리밍(WebRTC 등)은 손실된 데이터를 건너뛰어 화면이 깨지는 현상이 생기지만 실시간 재생은 유지됩니다. 이것이 라이브 동영상이 흔히 UDP를 사용하는 이유입니다 — 순간적인 화면 깨짐이 재생이 밀리는 것보다 낫습니다.
참고 문헌
এই পৃষ্ঠাটি কি সহায়ক ছিল?