Infra Architecture/Network Fundamentals

Network Fundamentals - 07. 혼잡 제어

도로가 막히면 속도를 줄이는 이유 — TCP 혼잡 제어

2016년, Google은 자체 개발한 BBR(Bottleneck Bandwidth and Round-trip propagation time) 이라는 새로운 TCP 혼잡 제어 알고리즘을 공개했다. 기존 알고리즘(CUBIC) 대비 Google 내부 트래픽의 처리량을 4배 올렸다. 비결은 단순했다 — 기존 알고리즘이 "패킷 손실이 일어나면 속도를 줄인다"고 가정한 반면, BBR은 "네트워크의 실제 병목 대역폭과 지연을 측정해서 최적 속도를 계산한다"는 접근을 취했다. 같은 도로를 달리는데 — 한 운전자는 "사고가 나야 속도를 줄이고", 다른 운전자는 "앞이 막히는지 실시간으로 확인하며 속도를 조절하는" 차이. 이 글은 TCP가 네트워크 혼잡에 어떻게 대응하는지를 다룬다.

이 글은 혼잡 제어(congestion control) — TCP가 네트워크가 혼잡할 때 전송 속도를 줄이고, 여유가 생기면 다시 올리는 메커니즘 — 를 다룬다. 이전 글에서 본 TCP의 신뢰성(재전송·순서 보장) 위에, 혼잡 제어가 얹히는 층이다. CUBIC(Linux 기본)과 BBR(Google 개발)의 차이, 패킷 손실이 왜 성능에 큰 영향을 미치는지, bufferbloat가 왜 문제인지를 본다. foundations 02에서 본 "지연(latency)" 품질 속성이 — 이 혼잡 제어에서 크게 좌우된다.

혼잡 제어가 왜 필요한가

인터넷은 공유 자원이다. 한 라우터의 대역폭을 여러 TCP 연결이 공유한다. 아무도 속도를 안 줄이면 — 라우터의 버퍼가 가득 차고, 패킷이 손실되고, 모든 연결이 재전송을 시작하고, 결국 네트워크가 마비된다(혼잡 붕괴, congestion collapse). 이런 일이 1986년 10월 실제로 일어났다 — 인터넷(당시 NSFNET)의 처리량이 32Kbps로 떨어졌다. 원인은 혼잡 제어가 없어서.

이 사건을 계기로 Van Jacobson이 1988년 TCP에 혼잡 제어를 도입했다. 핵심 아이디어는 — 각 TCP 연결이 "네트워크가 감당할 수 있는 속도"를 스스로 추정하고, 그 이하로 전송하는 것. 비유하자면 — 도로 위의 모든 운전자가 "앞이 막히면 속도를 줄이고, 뻥 뚫리면 속도를 올리는" 자율 주행 시스템. 중앙 통제 없이 각자가 판단한다.

cwnd — 혼잡 윈도우

TCP 혼잡 제어의 핵심 변수가 cwnd(congestion window, 혼잡 윈도우) 다. cwnd는 — "한 번에 네트워크에 보낼 수 있는 데이터의 양"이다. cwnd가 10패킷이면, ACK를 받기 전에 10패킷까지 보낼 수 있다. cwnd가 크면 처리량이 높고, cwnd가 작으면 처리량이 낮다.

혼잡 제어는 — 이 cwnd를 동적으로 조절한다. 네트워크가 여유로우면 cwnd를 키우고(더 빨리 보냄), 혼잡의 징후(패킷 손실)가 보이면 cwnd를 줄인다(천천히 보냄).

TCP 혼잡 제어의 네 단계

전통적 TCP 혼잡 제어(Reno·NewReno·CUBIC)는 네 단계로 cwnd를 조절한다.

1. Slow Start(느린 시작) — 연결 시작 시 cwnd를 작게(1 ~ 10 패킷) 시작. 매 ACK마다 cwnd를 1씩 늘린다. 즉 — 매 왕복(RTT)마다 cwnd가 두 배가 된다(지수적 증가). "처음엔 조심스럽게, 네트워크가 괜찮으면 빠르게 속도를 올린다." cwnd가 ssthresh(slow start threshold) 에 도달하면 — 다음 단계로 전환.

2. Congestion Avoidance(혼잡 회피) — cwnd가 ssthresh를 넘으면, 증가 속도를 줄인다. 매 RTT마다 cwnd를 1만큼 늘린다(선형적 증가). "조심스럽게 속도를 올린다."

3. Fast Retransmit(빠른 재전송) — 패킷 손실을 감지하면(중복 ACK 3회 수신), 손실된 패킷을 즉시 재전송한다. 타임아웃을 기다리지 않는다.

4. Fast Recovery(빠른 회복) — 손실 감지 후 cwnd를 절반으로 줄이고, 다시 선형적으로 증가시킨다. "사고가 났으니 속도를 절반으로 줄이고, 다시 조심스럽게 올린다."

flowchart TD
    START["연결 시작<br/>cwnd=1"] --> SS["Slow Start<br/>지수적 증가"]
    SS -->|"cwnd ≥ ssthresh"| CA["Congestion Avoidance<br/>선형적 증가"]
    CA -->|"패킷 손실 (3 dup ACK)"| FR["Fast Retransmit<br/>+ Fast Recovery"]
    FR -->|"cwnd 절반으로"| CA
    SS -.->|"패킷 손실"| FR

이 네 단계의 결과 — TCP의 처리량은 톱니바퀴(sawtooth) 패턴을 보인다. cwnd가 올라갔다가(혼잡), 손실로 반 토막 나고, 다시 올아가기를 반복하는 것이다.

BDP — 파이프를 얼마나 채워야 하는가

BDP(Bandwidth-Delay Product, 대역폭-지연 곱) 는 혼잡 제어를 이해하는 핵심 개념이다. BDP = 대역폭(bandwidth) x RTT(round-trip time). "네트워크 파이프에 한 번에 들어갈 수 있는 데이터의 양"이다. 비유하자면 — 수도관의 용량이다. 수도관이 굵고(대역폭) 길면(RTT), 한 번에 많은 물(데이터)이 파이프 안에 들어 있다. TCP의 cwnd는 — 이 파이프를 딱 채울 만큼이 최적이다. cwnd가 BDP보다 작으면 — 파이프가 비어 있어서 대역폭이 낭비된다(처리량 저하). cwnd가 BDP보다 크면 — 파이프가 넘쳐서 라우터 버퍼에 데이터가 쌓이고 지연이 증가한다(bufferbloat).

구체적 예로 보자. 서버 간 연결이 10Gbps 대역폭, 10ms RTT라고 치면:

  • BDP = 10Gbps x 10ms = 10,000,000,000 비트/초 x 0.01초 = 100,000,000 비트 = 12.5MB
  • cwnd가 12.5MB(약 8,300개의 1500바이트 패킷)여야 파이프가 딱 참
  • cwnd가 이보다 작으면 — 10Gbps 대역폭을 못 채움. 처리량 저하
  • cwnd가 이보다 크면 — 중간 라우터의 버퍼에 데이터가 쌓임. 지연 증가

이게 왜 중요한가 — 고대역폭·고지연 네트워크(long fat network) 에서 전통 TCP(Reno)의 혼잡 제어가 비효율적이기 때문이다. 패킷 손실이 나면 cwnd를 절반으로 줄이는데 — BDP가 큰 네트워크에서 절반으로 줄이면 처리량이 크게 떨어지고, 회복하는 데 오래 걸린다. CUBIC과 BBR이 이 문제를 개선한 것이다.

흐름 제어 vs 혼잡 제어 — 자주 혼동하는 두 개념

이전 글에서 TCP의 흐름 제어(flow control) 를 언급했다. 흐름 제어와 혼잡 제어는 다르다 — 자주 혼동되니 구분하자.

  • 흐름 제어(flow control)받는 쪽이 처리 못 할 만큼 빨리 보내지 않도록 조절. "나 지금 바빠, 좀 천천히 보내"라는 받는 쪽의 요청. 슬라이딩 윈도우(window size)로 표현. 두 당사자 간의 문제.
  • 혼잡 제어(congestion control)네트워크 중간(라우터·스위치)이 감당 못 할 만큼 빨리 보내지 않도록 조절. "네트워크가 막히고 있어, 속도 줄여"라는 시스템 전체의 보호. cwnd로 표현. 네트워크 전체의 문제.

비유하자면 — 흐름 제어는 "상대방이 받아적는 속도에 맞춰 말하기"고, 혼잡 제어는 "전화선 자체가 과부하 걸리지 않게 말하기"다. 둘 다 필요하지만, 다른 층의 문제를 푼다.

CUBIC — Linux의 기본 혼잡 제어

CUBIC은 2008년에 발표된 혼잡 제어 알고리즘으로, Linux 커널 2.6.19부터 기본이다. 이름이 CUBIC인 이유는 — cwnd의 증가 곡선이 세제곱(cubic) 함수 형태이기 때문. 패킷 손실 후 cwnd를 줄였다가, 처음엔 빠르게(세제곱 곡선의 가파른 부분), 나중엔 느리게(곡선이 완만해지는 부분) 회복한다. CUBIC의 장점은 — 고대역폭·고지연 네트워크(BDP, Bandwidth-Delay Product가 큰 네트워크)에서 기존(Reno)보다 처리량이 좋다는 것. 단점은 — 패킷 손실을 "혼잡의 신호"로 쓰기 때문에, 무선 네트워크(패킷 손실이 혼잡이 아니라 무선 오류일 수 있음)에서 성능이 떨어진다.

BBR — 측정 기반 혼잡 제어

BBR(Bottleneck Bandwidth and Round-trip propagation time) 은 Google이 2016년에 개발한 혼잡 제어 알고리즘. CUBIC과의 근본적 차이는 — 패킷 손실이 아니라 "네트워크의 실제 병목 대역폭과 최소 지연(RTT)"을 측정해서 cwnd를 결정한다는 것.

CUBIC은 "패킷이 손실됐다 = 네트워크가 혼잡하다"라고 가정한다. 하지만 이 가정은 항상 맞지 않는다 — 무선 네트워크에서는 신호 간섭으로 패킷이 손실될 수 있고(혼잡이 아닌데 속도를 줄임), 데이터센터의 스위치 버퍼가 크면 패킷 손실이 나기 전에 버퍼가 가득 차서 지연이 폭발한다(bufferbloat, 아래 참조).

BBR은 패킷 손실 대신 — 실제로 도달하는 처리량(bottleneck bandwidth)과 왕복 지연(RTT)을 측정해서, 그 둘의 곱(BDP)을 cwnd로 사용한다. "네트워크 파이프에 딱 맞게 채운다"는 접근. 손실이 나지 않는 최적의 cwnd를 찾는 것이다.

특성 CUBIC BBR
혼잡 신호 패킷 손실 대역폭·RTT 측정
속도 회복 세제곱 곡선 (느림) 측정 기반 (빠름)
무선 네트워크 성능 저하 (손실=혼잡 오판) 성능 유지
bufferbloat 악화시킴 (버퍼 채움) 완화 (버퍼 안 채움)
Linux 기본 2008~ (기본값) 별도 활성화 필요
개발 학계 (2008) Google (2016)

BBR을 Linux에서 활성화하려면:

# 현재 혼잡 제어 알고리즘 확인
sysctl net.ipv4.tcp_congestion_control
# BBR 활성화
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr

BBR의 네 가지 상태

BBR은 연결 수명 동안 네 가지 상태를 순환하며 네트워크 상태를 측정하고 대응한다.

  1. STARTUP — 연결 시작 시. 대역폭을 탐색하며 cwnd를 빠르게 키운다. slow start와 비슷하지만 — 패킷 손실이 아니라 "처리량이 더 이상 안 늘어나는 지점"을 감지해서 STARTUP을 끝낸다.
  2. DRAIN — STARTUP에서 큐가 쌓였으니, 큐를 비우면서 최적 cwnd로 수렴한다.
  3. PROBE_BW — 정상 상태. 주기적으로 대역폭을 다시 측정하며 cwnd를 미세 조정. 네트워크 상태가 변하면(대역폭 증가 등) 자동으로 반영.
  4. PROBE_RTT — 주기적으로 최소 RTT를 다시 측정. cwnd를 잠시 아주 작게 줄여서 큐가 비웠을 때의 RTT(진짜 전파 지연)를 잰다. BBR이 "네트워크 파이프의 실제 용량"을 아는 핵심 단계.

BBR의 실제 성과

Google이 2016년에 발표한 BBR의 내부 성과는 인상적이었다:

  • Google 내부 WAN 트래픽의 처리량 4배 증가
  • BBR을 쓰는 연결의 RTT 11배 감소 (버퍼를 안 채우니 지연이 줄음)
  • Africa·India 같은 패킷 손실률이 높은 네트워크에서 — CUBIC은 손실 때문에 거의 못 쓸 정도로 느렸지만, BBR은 정상 처리량 유지

2026년 기준 — BBR은 Google·Cloudflare·Spotify·Tencent 등 대규모 서비스에서 채택됐다. YouTube의 영상 스트리밍 처리량이 BBR 도입 후 크게 향상됐다.

bufferbloat — 버퍼가 너무 크면 생기는 문제

Bufferbloat(버퍼블로트) 는 — 네트워크 장비(라우터·스위치·모뎀)의 버퍼가 너무 커서 — 패킷 손실 대신 지연이 폭발하는 현상이다. CUBIC은 패킷 손실이 나야 속도를 줄인다. 근데 버퍼가 크면 — 패킷이 버퍼에 쌓이고 손실이 안 난다. CUBIC은 "손실이 안 났으니 속도를 계속 올린다". 결국 버퍼가 가득 차고 — 모든 패킷이 버퍼에서 대기하면서 지연이 수백 ms ~ 수 초로 폭발한다.

비유하자면 — 병목 도로에 차가 밀리는데, 도로 끝에 주차장(버퍼)이 너무 커서 차가 주차장에 가득 들어간다. 주차장이 가득 차야(패킷 손실) "아, 막히네"라고 인식하는데 — 그 전에 이미 주차장 안에서 엉망이 돼 있다. BBR은 주차장 크기에 의존하지 않고 도로 자체의 속도를 측정하니 — bufferbloat를 완화한다.

ECN — 패킷 손실 이전에 혼잡을 알리는 기술

ECN(Explicit Congestion Notification, RFC 3168) 은 — 라우터가 패킷 손실이 나기 전에 "혼잡이 오고 있다"고 수신자에게 알리는 기술이다. IP 헤더의 ECN 비트(2비트)를 라우터가 설정하면 — 수신자가 송신자에게 "속도 좀 줄여"라고 알려준다. 패킷을 손실시키지 않고 혼잡을 알리니 — 지연과 재전송이 줄어든다. ECN은 2026년 기준으로 데이터센터 네트워크에서 널리 쓰이고(DCTCP·L4S), 인터넷에서는 점진적으로 보급되고 있다.

DCTCP — 데이터센터를 위한 혼잡 제어

데이터센터는 — 낮은 지연(수십 마이크로초)과 높은 대역폭(10 ~ 100Gbps)이 동시에 필요한 환경이다. 일반 TCP(CUBIC)는 데이터센터 환경에서 비효율적이다 — 패킷 손실이 나야 속도를 줄이는데, 데이터센터 스위치의 버퍼가 작아서 미세한 혼잡에도 손실이 발생하고 처리량이 크게 떨어진다.

DCTCP(Data Center TCP) 는 Microsoft Research가 개발한 데이터센터 특화 혼잡 제어. ECN을 적극 활용해서 — 스위치 큐가 찰 때(임계값 도달) ECN 마킹을 하고, 송신자가 즉시 cwnd를 줄인다. 패킷 손실이 나기 전에 대응하니 — 처리량 저하 없이 낮은 지연을 유지한다. DCTCP는 데이터센터 네트워크(특히 RDMA/RoCE 환경)에서 널리 쓰인다.

Bufferbloat 완화 — fq_codel과 CAKE

BBR이 송신자 측에서 bufferbloat를 완화한다면, 수신자/라우터 측에서도 완화 기술이 있다. Linux의 큐 disciplines(qdisc)가 그 역할이다.

  • fq_codel — Linux 커널의 기본 qdisc(2026년). 각 TCP 연결을 별도 큐로 관리(flow-based fairness)하고, 큐가 길어지면 지능적으로 패킷을 드롭(AQM, Active Queue Management). 단순한 FIFO 큐와 달리 — 한 연결이 큐를 독점하지 못하게 막는다.
  • CAKE(Common Applications Kept Enhanced) — fq_codel의 후계자. 대역폭 제한·플로우 격리·Diffserv 우선순위를 하나의 qdisc로 통합. 가정용 라우터(OpenWrt)에서 인기.
# 현재 qdisc 확인
tc qdisc show dev eth0
# fq_codel 설정
sudo tc qdisc replace dev eth0 root fq_codel
# CAKE 설정 (대역폭 100Mbps)
sudo tc qdisc replace dev eth0 root cake bandwidth 100M

패킷 손실이 성능에 미치는 영향 — 숫자로 보기

패킷 손실이 TCP 처리량에 미치는 영향은 — 직관보다 훨씬 크다. Mathis 공식이라는 경험적 공식이 있다:

처리량 ≈ MSS / (RTT x sqrt(p))
  • MSS = 최대 세그먼트 크기 (보통 1460바이트)
  • RTT = 왕복 지연 (초)
  • p = 패킷 손실률 (예: 0.01 = 1%)

이 공식으로 — 10Gbps 링크, RTT 50ms, 패킷 손실률 0.1%인 경우의 처리량을 계산하면:

  • 처리량 ≈ 1460 x 8 / (0.05 x sqrt(0.001)) ≈ 2.3 Mbps

10Gbps 링크에서 — 단 0.1%의 패킷 손실률만으로도 처리량이 2.3Mbps로 폭락한다. 이게 CUBIC의 근본적 한계다 — 손실 기반 혼잡 제어는 손실률에 지나치게 민감하다. BBR이 손실에 덜 민감한 이유가 여기에 있다. 무선 네트워크(손실률 1 ~ 5% 흔함)에서 CUBIC이 거의 못 쓰는 이유도 같다.

손실률 예상 처리량 (10Gbps, RTT 50ms) 일반 TCP(CUBIC) 영향
0% 10 Gbps 최대 성능
0.001% ~7.5 Gbps 거의 영향 없음
0.01% ~2.3 Gbps 성능 저하 시작
0.1% ~730 Mbps 심각한 저하
1% ~230 Mbps 사실상 사용 불가

BBR은 이 손실 민감도에서 벗어난다 — 손실률 1%에서도 처리량이 거의 유지된다. 이게 Google이 무선 환경(Africa·India)에서 BBR을 도입해 효과를 본 이유다.

혼잡 제어는 "공유 자원을 공정하게 나누는 기술"이다

혼잡 제어 알고리즘 선택 — 실무 가이드

혼잡 제어 알고리즘은 — 워크로드와 네트워크 환경에 따라 선택해야 한다.

환경 권장 알고리즘 이유
일반 웹 서비스 (유선) CUBIC (기본) 안정적, 검증됨
모바일·무선 환경 BBR 패킷 손실(무선 오류)에 민감하지 않음
고대역폭·고지연 (WAN) BBR BDP 기반 최적화로 처리량 향상
데이터센터 (저지연) DCTCP ECN 기반, 마이크로초 지연
클라우드 VM CUBIC 또는 BBR 벤치마크 후 선택
VPN·터널 BBR 터널 내 패킷 손실이 혼잡 아님

BBR로 전환하기 전에 — 벤치마크를 해야 한다. 일부 환경에서 CUBIC보다 나쁠 수 있다(BBR이 너무 "적극적으로" 대역폭을 차지해서 다른 CUBIC 연결이 굶주리는 현상, fairness 문제).

실습 — 혼잡 제어 상태 확인

1. 현재 혼잡 제어 알고리즘

# 현재 알고리즘
sysctl net.ipv4.tcp_congestion_control
# 사용 가능한 알고리즘 목록
sysctl net.ipv4.tcp_available_congestion_control

확인할 것: cubic이 기본. bbr이 보이면 — BBR을 켤 수 있다(커널 모듈 로드 필요).

2. BBR 활성화 (재부팅 시 유지하려면 /etc/sysctl.conf)

sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
# 영구 적용
echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.d/99-bbr.conf

확인할 것: sysctl net.ipv4.tcp_congestion_controlbbr로 바뀌었는지. 클라우드 VM에서는 커널 버전에 따라 BBR이 안 될 수 있음(커널 4.9+ 필요).

3. 네트워크 지연과 손실률 확인

# 목적지까지의 지연과 패킷 손실
ping -c 10 8.8.8.8
# 더 자세하게 — mtr
mtr 8.8.8.8 2>/dev/null || echo "mtr 미설치"

확인할 것: pingtime이 일정한가(정상), 변동이 큰가(혼잡 또는 bufferbloat). Loss가 0%가 아니면 패킷 손실 — CUBIC에서는 처리량 저하로 직결.

4. TCP 연결의 RTT와 cwnd (ss)

# 연결별 RTT와 송신/수신 윈도우
ss -ti | head -20

확인할 것: rtt 값(왕복 지연, ms)과 cwnd 값(혼잡 윈도우, 패킷 수). RTT가 높고 cwnd가 작으면 — 처리량이 낮다(BDP가 큰 네트워크에서 흔함).

미검증: BBR 활성화는 커널 4.9+에서 가능. 클라우드 VM의 커널 버전 확인 필요. mtr·ss -ti는 별도 설치 또는 root 권한 필요할 수 있음.

혼잡 제어는 "공유 자원을 공정하게 나누는 기술"이다

혼잡 제어를 이해하면 — "왜 대역폭이 충분한데 처리량이 낮은가?"(패킷 손실로 cwnd가 줄었으니까), "왜 지연이 수백 ms로 폭발하는가?"(bufferbloat), "왜 클라우드에서 BBR을 켜면 성능이 좋아지는가?"(손실 대신 측정 기반으로 cwnd를 결정하니까)에 답할 수 있다.

다음 글에서는 L7(응용 계층)로 올라간다 — DNS. 도메인 이름(example.com)을 IP 주소(93.184.216.34)로 변환하는 시스템. "이름"과 "주소"를 연결하는 인터넷의 전화번호부가 어떻게 동작하는지를 본다.

BBR의 공정성 문제는 — 활발히 연구 중인 주제다. BBR 연결이 CUBIC 연결과 같은 링크를 공유하면 — BBR이 대역폭을 더 많이 차지하는 경향이 있다(BBR은 손실로 속도를 안 줄이니까). 이를 해결하기 위해 BBR v2(2024년 개발 중)는 — 공정성과 RTT 공정성을 개선하는 방향으로 발전하고 있다.
혼잡 제어는 — "공유 자원을 공정하게 나누는 기술"이다. 각 TCP 연결이 네트워크 상태를 추정하고 자발적으로 속도를 조절함으로써 — 중앙 통제 없이 인터넷이 안정적으로 작동한다. CUBIC에서 BBR로의 전환은 — "패킷 손실 기반"에서 "측정 기반"으로의 패러다임 전환이다.

혼잡 제어의 핵심 — cwnd(혼잡 윈도우)를 동적으로 조절해, 네트워크가 감당할 수 있는 속도로 전송하는 것. CUBIC은 손실 기반, BBR은 측정 기반이다. BBR이 모든 환경에서 CUBIC보다 좋은 건 아니지만 — 무선·고지연 환경에서의 이점이 분명하다. 알고리즘 선택은 워크로드와 환경에 따라 벤치마크 후 결정해야 한다.


참고

  • Jacobson, V. "Congestion Avoidance and Control", SIGCOMM 1988 — TCP 혼잡 제어 원논문. 접근 2026-07-21
  • Ha, S., Rhee, I., Xu, L. "CUBIC: A New TCP-Friendly High-Speed TCP Variant", ACM TOPEP 2008 — CUBIC 원논문. 접근 2026-07-21
  • Cardwell, N. et al. "BBR: Congestion-Based Congestion Control", CACM 2017 — BBR 원논문. 접근 2026-07-21
  • RFC 3168, Ramakrishnan, K. et al. "The Addition of Explicit Congestion Notification (ECN) to IP", 2001 — ECN 표준. 접근 2026-07-21
  • Gettys, J., Nichols, K. "Bufferbloat: Dark Buffers in the Internet", CACM 2012 — bufferbloat 원인 분석. 접근 2026-07-21
  • Kurose, J. F., Ross, K. W. 8th ed, 2021, Ch.3 — 혼잡 제어. 접근 2026-07-21
  • Gregg, B. 2nd ed, 2020, Ch.10 — 네트워크 성능 분석. 접근 2026-07-21