TCP 흐름 제어와 혼잡 제어 (TCP Flow Control and Congestion Control)

한눈에 보기

흐름 제어는 수신자의 버퍼를, 혼잡 제어는 네트워크를 보호하는 TCP의 속도 조절 기능이다. 슬라이딩 윈도우, 슬로 스타트와 AIMD, CUBIC과 BBR까지 정리한다.

최종 업데이트 2026.09.17

TCP 흐름 제어(flow control)는 수신자가 처리할 수 있는 만큼만 보내도록 송신 속도를 조절하는 기능이고, 혼잡 제어(congestion control)는 네트워크 경로가 감당할 수 있는 만큼만 보내도록 조절하는 기능이다. 흐름 제어는 수신자의 버퍼를 보호하고 혼잡 제어는 네트워크 전체를 보호한다는 점에서 목적이 다르다. TCP 송신자는 두 제약 중 더 작은 값을 한도로 삼아 전송량을 결정한다.

왜 두 가지 제어가 모두 필요한가

수신 애플리케이션이 데이터를 느리게 소비하면 수신 버퍼가 넘쳐 도착한 데이터가 버려진다. 이것을 막는 것이 흐름 제어다. 한편 수신자는 여유가 있어도 중간의 라우터 큐가 가득 차면 패킷이 손실된다. 모든 송신자가 손실을 무시하고 계속 밀어 넣으면 재전송이 재전송을 부르는 혼잡 붕괴(congestion collapse)가 일어나는데, 실제로 1980년대 인터넷이 이를 겪은 뒤 혼잡 제어가 TCP에 도입되었다. 요약하면 흐름 제어의 병목은 종단의 수신자이고, 혼잡 제어의 병목은 경로 중간의 네트워크라는 점을 먼저 구분해야 한다.

흐름 제어: 슬라이딩 윈도우

세그먼트 하나를 보내고 ACK를 기다리는 정지-대기 방식은 왕복 시간 동안 회선이 놀게 되어 처리량이 왕복 시간에 반비례해 떨어진다. 그래서 TCP는 확인 응답을 기다리지 않고 일정량을 연속 전송하는 슬라이딩 윈도우(sliding window) 방식을 쓴다. 수신자는 ACK를 보낼 때마다 자신의 버퍼 여유 공간을 수신 윈도우(rwnd, receive window) 필드에 실어 알려 주고, 송신자는 확인받지 못한 데이터의 양이 이 값을 넘지 않도록 한다. ACK가 도착해 윈도우가 앞으로 미끄러지면 그만큼 새 데이터를 보낼 수 있다.

수신 버퍼가 가득 차면 rwnd가 0이 되어 송신이 멈춘다. 이후 여유가 생겼다는 윈도우 갱신 통지가 유실되면 양쪽이 영원히 기다리는 교착이 생길 수 있으므로, 송신자는 작은 탐침 패킷을 주기적으로 보내 윈도우 상태를 확인한다. 원래 윈도우 필드는 16비트라 64KB가 상한이지만, 고대역 장거리 회선을 위해 윈도우 스케일(window scale) 옵션으로 기가바이트급까지 확장한다.

혼잡 제어: 네 가지 기본 동작

송신자는 네트워크 상태를 직접 알 수 없으므로, 혼잡 윈도우(cwnd, congestion window)라는 자체 추정치를 유지하며 손실과 지연 신호로 조절한다. 고전적인 절차는 다음과 같다.

  1. 슬로 스타트(slow start): 작은 cwnd로 시작해 ACK를 받을 때마다 늘려서 왕복마다 대략 두 배로 키운다. 이름과 달리 증가 속도는 지수적이다.
  2. 혼잡 회피(congestion avoidance): cwnd가 임계값(ssthresh)에 도달하면 왕복당 1세그먼트씩 선형으로 늘리며 조심스럽게 한계를 탐색한다.
  3. 빠른 재전송(fast retransmit): 같은 번호의 중복 ACK가 3번 도착하면 타임아웃을 기다리지 않고 해당 세그먼트를 즉시 재전송한다.
  4. 빠른 회복(fast recovery): 중복 ACK로 감지한 손실은 가벼운 혼잡으로 보고 cwnd를 절반으로 줄여 혼잡 회피부터 다시 진행한다. 반면 타임아웃은 심각한 혼잡으로 보고 cwnd를 1로 되돌려 슬로 스타트부터 다시 시작한다.

이렇게 선형으로 늘리고 손실 시 절반으로 줄이는 패턴을 AIMD(Additive Increase Multiplicative Decrease)라고 하며, 여러 흐름이 대역폭을 공평하게 나누어 갖도록 수렴시키는 성질이 있다.

현대의 혼잡 제어 알고리즘

손실 기반 고전 알고리즘(Reno 계열)은 대역폭이 크고 지연이 긴 회선에서 회복이 느리다는 한계가 있다. 리눅스 기본값인 CUBIC은 감소 이후 3차 함수 곡선으로 빠르게 회복해 고속 회선 활용도를 높였다. 구글이 설계한 BBR(Bottleneck Bandwidth and Round-trip propagation time)은 손실을 기다리는 대신 병목 대역폭과 최소 왕복 시간을 직접 측정해 전송률을 정하므로, 라우터 큐를 가득 채워 지연을 키우는 버퍼블로트(bufferbloat) 문제를 완화한다. 또한 패킷을 버리기 전에 혼잡 조짐을 표시해 알리는 ECN(Explicit Congestion Notification)도 손실 없이 혼잡을 전달하는 보조 수단으로 쓰인다. QUIC도 같은 혼잡 제어 원리를 사용자 공간에서 구현해 알고리즘 교체가 더 쉽다. 결국 어떤 알고리즘이든 "네트워크 상태를 어떤 신호로 추정하고, 얼마나 공격적으로 대역폭을 차지할 것인가"라는 같은 질문에 대한 서로 다른 답이라고 이해하면 된다.

흐름 제어와 혼잡 제어 비교

구분흐름 제어혼잡 제어
보호 대상수신자의 버퍼네트워크 경로(라우터 큐)
제어 주체수신자가 rwnd로 알림송신자가 cwnd를 추정
정보의 출처ACK에 실린 명시적 값손실, 지연, ECN 등 간접 신호
핵심 기법슬라이딩 윈도우, 윈도우 스케일슬로 스타트, AIMD, CUBIC, BBR
실제 송신 한도min(rwnd, cwnd)min(rwnd, cwnd)

면접에서 이렇게 물어본다

  • 흐름 제어와 혼잡 제어의 차이를 보호 대상과 제어 주체 관점에서 설명해 보라.
  • 슬라이딩 윈도우가 정지-대기 방식보다 처리량이 높은 이유는 무엇인가.
  • 슬로 스타트와 혼잡 회피는 각각 어떤 방식으로 윈도우를 키우고 언제 전환되는가.
  • 중복 ACK 3개로 감지한 손실과 타임아웃으로 감지한 손실은 왜 다르게 처리하는가.
  • CUBIC과 BBR은 기존 방식의 어떤 한계를 어떻게 개선했는가.
네트워크 문서 전체 보기

이 개념, 내 코드에서는 어떻게 물어볼까요

데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.

공고 넣고 시작하기