배려하는 대상이 다르다
둘 다 “너무 빨리 보내지 않게 하는 장치”라 헷갈리기 쉽다. 차이는 누구를 위해 속도를 줄이는가에 있다.
- 흐름 제어 — 수신자가 감당할 수 있는 만큼만 보낸다
- 혼잡 제어 — 네트워크가 감당할 수 있는 만큼만 보낸다
흐름 제어 — 상대가 알려준다
수신자에게는 받은 데이터를 쌓아두는 버퍼가 있다. 애플리케이션이 읽어가는 속도보다 빨리 도착하면 버퍼가 찬다.
TCP 헤더에는 수신 윈도우(rwnd) 필드가 있다. 수신자가 ACK를 보낼 때마다 “지금 이만큼 더 받을 수 있다”를 적어 보낸다. 송신자는 그 범위를 넘지 않는다.
버퍼가 가득 차면 0을 보낸다. 송신자는 전송을 멈추고, 주기적으로 작은 탐색 패킷을 보내 공간이 생겼는지 확인한다.
핵심은 수신자가 자기 사정을 직접 알려준다는 점이다. 정확한 값이라 추측할 필요가 없다.
혼잡 제어 — 스스로 추측한다
네트워크 중간의 라우터에도 큐가 있다. 여기가 넘치면 패킷이 버려진다. 그런데 라우터는 “지금 혼잡하다”고 알려주지 않는다.
그래서 송신자는 간접 신호로 추측한다. 패킷 유실(재전송 타임아웃, 중복 ACK)이 곧 혼잡의 신호다.
송신자는 혼잡 윈도우(cwnd)를 스스로 관리한다.
- 슬로 스타트 — 작게 시작해 ACK를 받을 때마다 배로 늘린다. 한계를 빠르게 찾는다
- 혼잡 회피 — 임계치를 넘으면 조금씩(선형) 늘린다
- 유실 감지 — 윈도우를 크게 줄이고 다시 늘린다
늘릴 때는 천천히, 줄일 때는 과감하게. 여러 연결이 대역폭을 나눠 쓰면서도 무너지지 않게 하는 규칙이다.
실제 전송량
전송 가능량 = min(rwnd, cwnd)
둘 중 작은 쪽이 상한이다. 수신자가 여유로워도 네트워크가 막히면 못 보내고, 네트워크가 한가해도 수신자가 느리면 못 보낸다.
왜 둘 다 필요한가
하나만으로는 다른 쪽 문제를 못 본다.
- 흐름 제어만 있으면: 수신자는 멀쩡한데 중간 라우터가 무너진다
- 혼잡 제어만 있으면: 네트워크는 한가한데 느린 수신자의 버퍼가 넘친다
정리
흐름 제어는 상대가 알려주는 값이고 혼잡 제어는 스스로 추정하는 값이다. 이 차이가 두 메커니즘의 동작을 갈라놓는다.