🚦
혼잡 제어가 필요한 이유
여러 연결이 하나의 회선을 함께 쓰는 인터넷에서, 모두가 최대 속도로 데이터를 쏟아내면 라우터 버퍼가 넘쳐 오히려 전체 성능이 나빠집니다.
TCP는 데이터를 보내고 받는 두 컴퓨터뿐 아니라, 그 사이를 지나는 라우터와 회선까지 공유해서 씁니다. 만약 송신 측이 회선 상황을 고려하지 않고 무작정 빠르게 데이터를 보내면 중간 라우터의 버퍼가 넘쳐 패킷 손실이 급증하고, 이는 재전송을 유발해 오히려 전체 네트워크의 효율이 급격히 떨어지는 "혼잡 붕괴"로 이어질 수 있습니다. 혼잡 제어는 이런 상황을 막기 위해 송신 속도를 네트워크 상태에 맞게 스스로 조절하는 TCP의 핵심 메커니즘입니다.
📦
혼잡 윈도우(cwnd)란
상대방의 확인 응답을 기다리지 않고 한 번에 내보낼 수 있는 데이터 양을 나타내는 값으로, 혼잡 제어 알고리즘이 이 값을 계속 조절합니다.
TCP 송신 측은 "혼잡 윈도우(cwnd, congestion window)"라는 값만큼의 데이터를 확인 응답(ACK) 없이도 미리 내보낼 수 있습니다. 이 값이 클수록 한 번에 더 많은 데이터를 보낼 수 있어 처리량이 늘지만, 너무 크면 네트워크가 감당하지 못해 손실이 발생합니다. 혼잡 제어 알고리즘의 핵심은 결국 이 cwnd 값을 상황에 맞게 늘렸다 줄였다 하는 규칙을 정하는 것입니다.
🐢
슬로우 스타트 - 조금씩 늘려가며 속도 탐색
연결 초반에는 작은 혼잡 윈도우로 시작해, 응답이 성공적으로 올 때마다 지수적으로 윈도우를 키워가며 네트워크가 감당할 수 있는 속도를 빠르게 찾아갑니다.
연결이 막 시작되면 TCP는 네트워크 상태를 전혀 알지 못하므로, 매우 작은 혼잡 윈도우(보통 패킷 몇 개 수준)로 조심스럽게 시작합니다. 확인 응답을 받을 때마다 윈도우 크기를 두 배로 늘려가며 빠르게 적정 속도를 탐색하다가, 손실이 발생하거나 정해둔 임계값에 도달하면 슬로우 스타트를 마치고 좀 더 완만하게 늘리는 혼잡 회피 단계로 넘어갑니다.
📉
혼잡 회피 - 손실 신호를 받으면 속도를 줄이는 방식
패킷 손실이 감지되면 네트워크가 혼잡하다는 신호로 해석해 혼잡 윈도우를 큰 폭으로 줄인 뒤, 다시 조금씩 늘려가며 적정선을 찾습니다.
전통적인 혼잡 제어는 패킷 손실을 "네트워크가 혼잡하다"는 신호로 해석합니다. 손실이 감지되면 혼잡 윈도우를 절반으로 줄이는 등 보수적으로 대응한 뒤, 이후에는 손실이 없는 동안 윈도우를 선형적으로 서서히 늘려가는 방식으로 적정 전송 속도를 계속 찾아갑니다. 이 늘렸다 줄이는 패턴이 반복되면서 그래프로 그리면 톱니 모양의 특징적인 곡선이 나타납니다.
🕰️
Reno·New Reno - 손실 기반 고전 알고리즘
1990년대에 등장한 초기 혼잡 제어 알고리즘으로, 패킷 손실만을 혼잡의 신호로 삼는 가장 단순하고 오래된 방식입니다.
TCP Reno는 슬로우 스타트와 혼잡 회피, 빠른 재전송·빠른 회복 기법을 결합해 손실이 발생하면 즉시 윈도우를 줄이고 재빠르게 회복하도록 설계된 알고리즘입니다. New Reno는 한 번에 여러 패킷이 손실됐을 때의 회복 속도를 개선한 버전입니다. 다만 대역폭이 매우 큰 고속 회선에서는 손실 이후 회복 속도가 느려 회선을 충분히 활용하지 못하는 한계가 있습니다.
📐
Cubic - 리눅스 기본값, 고대역폭 환경에 맞춘 개선
혼잡 윈도우가 시간에 따라 3차 함수(큐빅) 곡선을 그리며 늘어나도록 설계해, 손실 이후에도 대역폭을 더 빠르게 회복합니다.
Cubic은 오늘날 리눅스 커널의 기본 혼잡 제어 알고리즘으로, 윈도우 크기를 시간의 3차 함수로 조절합니다. 손실 직후에는 빠르게 이전 수준 가까이 회복한 뒤 점점 완만하게 증가시키다가, 이전에 손실이 발생했던 지점 근처에서는 다시 신중하게 접근하는 방식으로 동작합니다. 이 방식은 대역폭·지연시간이 큰 고속 장거리 회선에서 Reno 계열보다 훨씬 효율적으로 대역폭을 활용합니다.
📡
BBR - 손실 대신 대역폭·지연을 직접 측정하는 새로운 접근
구글이 개발한 BBR은 패킷 손실을 기다리는 대신, 실제 병목 대역폭과 최소 왕복 지연시간을 직접 측정해 전송 속도를 정합니다.
Reno나 Cubic 같은 손실 기반 알고리즘은 "손실이 나야만" 네트워크가 혼잡하다고 판단하는데, 이는 이미 버퍼가 가득 찬 뒤에야 반응한다는 한계가 있습니다(버퍼블로트 문제와 연결됩니다). BBR(Bottleneck Bandwidth and Round-trip propagation time)은 대신 실시간으로 병목 구간의 대역폭과 지연시간이 가장 짧을 때의 값을 계속 추정해, 손실이 발생하기 전에 최적의 전송 속도를 유지하려고 시도합니다. 유튜브 등 구글의 여러 서비스에 적용되어 있으며, 리눅스 커널에서도 선택적으로 사용할 수 있습니다.