[Network] TCP의 핵심: 흐름 제어(Flow Control)와 폭주 제어(Congestion Control) 완벽 정리

[Network] TCP의 핵심: 흐름 제어(Flow Control)와 폭주 제어(Congestion Control) 완벽 정리

TCP(Transmission Control Protocol)는 “신뢰성 있는 전송”을 제공하는 대표적인 전송 계층(L4) 프로토콜입니다.
하지만 ACK 하나 기다리면서 패킷을 한 개씩 보내는 구조였다면, 오늘날의 인터넷 속도는 상상도 할 수 없겠죠.

엔지니어 관점에서 TCP 흐름 제어(Flow Control)와 폭주 제어(Congestion Control)의 핵심 메커니즘을 한 번에 정리합니다.

  • TCP가 어떻게 신뢰성(순서 보장 + 유실 복구)을 제공하는지
  • 슬라이딩 윈도우(Sliding Window)가 실제로 어떻게 동작하는지
  • Flow Control vs Congestion Control이 정확히 무엇이 다른지
  • 슬로 스타트(Slow Start), 혼잡 회피(Congestion Avoidance), Fast Retransmit/Recovery까지

네트워크/시스템 엔지니어, 백엔드 개발자, 네트워크 공부하는 전기·정보통신 기사 준비생 모두를 타겟으로 했습니다.


1. TCP가 “신뢰성”을 만드는 기본 메커니즘

TCP는 단순히 “보냈다”로 끝나는 프로토콜이 아닙니다.
시퀀스 번호(Sequence Number)와 ACK(확인 응답), 그리고 재전송(Retransmission) 메커니즘으로 신뢰성을 구현합니다.

1-1. 시퀀스 번호(Sequence Number)와 순서 보장

  • TCP는 스트림(바이트 단위 데이터)에 시퀀스 번호를 부여합니다.
  • 예를 들어 3,000바이트를 MTU에 맞춰 1,460바이트씩 전송하면:
    • 1번째 세그먼트: SEQ = 1 (데이터 1~1460)
    • 2번째 세그먼트: SEQ = 1461 (데이터 1461~2920)
    • 3번째 세그먼트: SEQ = 2921 (데이터 2921~3000)
  • 수신 측은 SEQ를 기준으로 Out-of-Order 패킷도 재조립하여 상위 계층에 순서대로 전달합니다.

1-2. ACK과 재전송, RTO

송신 측은 데이터 전송 후 ACK를 통해 정상 도착 여부를 확인합니다.

  • 정상 흐름:
    • SEQ=1 세그먼트 전송 → 수신 측은 다음에 기대하는 시퀀스 번호(예: 1461)를 ACK로 회신
  • 타임아웃 기반 재전송(RTO, Retransmission Timeout):
    • 일정 시간(RTO) 안에 ACK가 도착하지 않으면, 송신 측은 해당 세그먼트를 유실로 간주하고 재전송
  • 중복 ACK(Duplicate ACK) 기반 Fast Retransmit:
    • 수신 측이 예를 들어 “다음으로 2921이 필요하다”는 ACK를 3번 이상 중복해서 보내면,
      송신 측은 타임아웃을 기다리지 않고 해당 세그먼트를 즉시 재전송 (Fast Retransmit)

💡 SACK(Selective ACK)
옵션을 사용하면 “어떤 구간은 받았고, 어떤 구간이 비어 있는지”를 블록 단위로 알려줄 수 있어,
송신 측이 정말 누락된 부분만 골라 재전송 가능 → 대역폭 효율 향상.


2. 흐름 제어(Flow Control): “수신 측”을 보호하는 메커니즘

TCP가 “한 패킷 보내고 ACK 기다리기”로만 동작한다면 RTT가 긴 환경에서는 극심한 비효율이 발생합니다.
이를 해결하는 것이 슬라이딩 윈도우(Sliding Window)이고,
그 안에서 수신 윈도우(RWND, Receive Window)가 흐름 제어(Flow Control)의 핵심 역할을 합니다.

2-1. 윈도우(Window)란?

“ACK를 기다리지 않고 한 번에 전송할 수 있는 데이터 양”

  • 송신 측은 윈도우 크기만큼 파이프에 채워 넣듯 여러 세그먼트를 연속으로 전송합니다.
  • 그 사이에 ACK가 도착하면, 확인된 부분만큼 윈도우를 옆으로 밀어서(슬라이딩) 다음 데이터를 전송합니다.

2-2. 슬라이딩 윈도우(Sliding Window) 동작 예시

  1. 초기 윈도우 = 4세그먼트
  2. SEQ=1,2,3,4를 연속 전송
  3. 수신 측이 “1~2까지 OK, 다음은 3 달라”는 ACK(3)을 반환
  4. 송신 측은 3,4번 세그먼트 상태를 확인한 뒤, 윈도우를 앞으로 밀고 5,6번 세그먼트를 전송

이렇게 해서 RTT 동안 전송량을 극대화하면서도 여전히 ACK 기반의 신뢰성을 유지할 수 있습니다.

2-3. 수신 윈도우(RWND)와 흐름 제어

문제는 수신 측 버퍼 크기입니다.
수신 측의 애플리케이션이 데이터를 빨리 처리하지 못하면 TCP 수신 버퍼가 가득 차게 되고, 그 상태에서 계속 데이터를 받으면 버퍼 오버플로우가 발생합니다.

이를 막기 위해:

  • 수신 측은 현재 버퍼 여유 공간을 바탕으로 수신 윈도우(RWND) 값을 계산
  • 이 값을 TCP 헤더의 Window 필드에 넣어 송신 측에 전달
  • 송신 측은 전송 가능한 양 ≤ RWND를 항상 만족하도록 전송량을 조절

👉 Flow Control 요약

  • 대상: 수신 호스트
  • 목적: 수신 버퍼 오버플로우 방지
  • 방법: 수신 측이 윈도우 크기(RWND)를 조절해 송신 측에 전달

3. 폭주 제어(Congestion Control): “네트워크 전체”를 보호하는 메커니즘

Flow Control이 “수신 호스트 하나의 상태”를 고려한다면,
Congestion Control(폭주 제어)은 “네트워크(라우터, 링크) 전체의 상태”를 고려합니다.

즉,

  • Flow Control: Receiver Friendly
  • Congestion Control: Network Friendly

TCP는 이를 위해 혼잡 윈도우(CWND, Congestion Window)라는 개념을 도입합니다.

3-1. 왜 폭주 제어가 필요할까?

예를 들어, 여러 호스트가 한꺼번에 10Gbps 링크로 데이터를 밀어 넣으면:

  • 라우터 큐(버퍼)가 가득 차고 패킷 드롭 증가
  • 재전송이 쌓이면서 혼잡이 더욱 심해짐
  • 결과적으로 전체 스루풋이 오히려 떨어지는 “혼잡 붕괴(Congestion Collapse)” 현상 발생

이를 막기 위해 TCP는 네트워크가 감당 가능한 수준에서
CWND를 동적으로 조절하며 스스로 속도를 제어합니다.


4. TCP 혼잡 제어 알고리즘: Slow Start ~ Fast Recovery

대표적인 TCP 혼잡 제어 알고리즘들은 보통 다음 4단계 로직(또는 변형)을 따릅니다.

  1. Slow Start
  2. Congestion Avoidance
  3. Fast Retransmit
  4. Fast Recovery

4-1. Slow Start (슬로 스타트)

이름은 Slow Start지만, 실제 증가는 굉장히 빠릅니다.

  • 초기 CWND는 보통 1 MSS(또는 그 근처 몇 MSS)에서 시작
  • 매 RTT마다 ACK 수에 비례해서 CWND가 2배씩 증가 (지수적 증가)

RTT 0: CWND = 1
RTT 1: CWND = 2
RTT 2: CWND = 4
RTT 3: CWND = 8 …

네트워크의 대역폭·지연 특성을 모르는 초기 단계에서
‘최대 허용치’를 빠르게 탐색하기 위한 전략
입니다.

여기서 임계값(threshold, ssthresh)를 도입하여
CWND가 ssthresh에 도달하면 Congestion Avoidance 단계로 전환합니다.

4-2. Congestion Avoidance (혼잡 회피)

혼잡 회피 단계에서는 CWND 증가 속도를 완만하게(선형) 조정합니다.

  • 슬로 스타트: 지수 증가 (2배, 4배, 8배 …)
  • 혼잡 회피: 1 MSS씩 선형 증가

이렇게 해서 네트워크를 크게 흔들지 않는 선에서
최대 스루풋을 찾아가는 동작을 합니다.

4-3. 패킷 유실 감지: 타임아웃 vs 중복 ACK

혼잡은 보통 패킷 유실로 감지합니다.
TCP에서는 두 가지 신호를 사용합니다.

  1. 타임아웃(RTO)
    • 가장 강력한 혼잡 신호
    • CWND를 1 MSS로 리셋하고,
    • ssthresh를 (이전 CWND/2) 수준으로 낮춘 뒤
    • Slow Start부터 다시 시작
  2. 중복 ACK 3회 (3 Dup ACK) – Fast Retransmit & Fast Recovery
    • 패킷 유실이 있긴 하지만 링크가 완전히 막힌 수준은 아님
    • 타임아웃보다 덜 공격적으로 반응
    • 일반적인 NewReno 계열 알고리즘에서는:
      • 해당 세그먼트를 즉시 재전송(Fast Retransmit)
      • CWND를 절반으로 줄이고, ssthresh 설정 후
      • 완전한 Slow Start로 돌아가기보다는
        Fast Recovery로 진입해서 빠르게 Congestion Avoidance 단계로 복귀

💡 요약

  • 타임아웃: “진짜 막혔다” → CWND 크게 줄이고, Slow Start 재시작
  • 3 Dup ACK: “조금 손실 났다” → CWND 절반으로 줄이고, 빠르게 회복 시도

5. Flow Control vs Congestion Control 정리 표

마지막으로 인터뷰/자격증 시험에서 자주 나오는
Flow Control vs Congestion Control 차이를 표로 정리하면 다음과 같습니다.

구분흐름 제어 (Flow Control)폭주 제어 (Congestion Control)
고려 대상수신 호스트(Receiver)의 버퍼 상태네트워크(라우터·링크)의 혼잡 상태
핵심 변수수신 윈도우(RWND)혼잡 윈도우(CWND)
목적수신 버퍼 오버플로우 방지혼잡 붕괴 방지, 공정한 대역폭 사용
동작 위치주로 End Host 간 TCP 연결End Host에서 구현되지만, 네트워크 전체 상태 반영
대표 메커니즘Window 광고, Zero Window, 슬라이딩 윈도우Slow Start, Congestion Avoidance, Fast Retransmit/Recovery

실제 송신 측 TCP 스택이 사용하는 실제 전송 가능 윈도우는 보통

Effective Window = min(RWND, CWND)

로 계산된다고 이해하면 됩니다.


6. 엔지니어 관점에서의 의미

현대 서버/네트워크 운영에서 TCP 흐름 제어·폭주 제어는 다음과 같은 의미를 갖습니다.

  • 고 RTT·고대역폭(Cloud, 해외 리전) 환경에서의 스루풋 최적화
  • 큐 관리(AQM), CoDel, RED 등 L3 장비의 혼잡제어와의 상호 작용
  • 큐 빌드업, 버퍼블로트(Bufferbloat) 문제 분석 시
    CWND/RWND 동작 이해는 필수
  • 리눅스 커널의 TCP 옵션 튜닝 (tcp_congestion_control, tcp_window_scaling 등) 시
    기본 메커니즘 이해 여부에 따라 결과가 크게 달라짐

정리하자면,
Flow Control = “내가 보내는 쪽이 상대 버퍼를 꽉 채우지 않게 조절하는 기술”
Congestion Control = “내 플로우가 네트워크 전체에 민폐를 안 끼치면서 최대 속도를 찾는 기술”
입니다.


7. 마무리 – TCP는 생각보다 “매너 좋은 프로토콜”

마지막으로 전체 그림을 한 줄로 정리하면 이렇습니다.

  1. 시퀀스 번호 + ACK + 재전송으로 신뢰성 확보
  2. 슬라이딩 윈도우 + Flow Control(RWND)로 수신 측 버퍼 보호
  3. Congestion Control(CWND)로 네트워크 전체 안정성 보장

TCP는 단순한 “바이트 스트림”이 아니라,
수신 호스트와 네트워크 모두를 배려하면서 최적의 전송 속도를 찾아가는 꽤 매너 좋은 프로토콜입니다.


코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다