TCP는 전송 프로토콜이다.
프로토콜은 클라이언트와 서버가 정보를 교환할 수 있도록 하는 메시지 형식 대한 규칙 이라고 보면 된다.
수신 호스트가 전송 받은 메시지를 이해하려면 설계된 규칙에 따라 작성된 데이터 형식이어야 한다는 말이다.
TCP는 연결 지향적(handshaking 기반)으로 동작하며, 송신자와 수신자 간에 신뢰성 있는 방식으로 전달하고,
흐름 제어와 혼잡 제어를 통해 수신자를 과부하시키지 않는 통신 규약이다.
TCP의 전송 제어 기법
TCP는 신뢰성 있는 데이터 전송을 보장하기 위해 다양한 제어 메커니즘을 사용한다.
그중에서도 가장 중요한 3가지는 다음과 같다
- 흐름 제어(Flow Control)
- 오류 제어(Error Control)
- 혼잡 제어(Congestion Control)
이 글에서는 이 세 가지 개념을 역할 중심으로 쉽게 정리해본다.
흐름 제어 (Flow Control)
송신자와 수신자의 데이터 처리 속도는 서로 다를 수 있다.
만약 송신자가 수신자의 처리 능력을 고려하지 않고 데이터를 계속 보내면,
수신자의 버퍼가 넘쳐 데이터 손실이 발생할 수 있다.
이를 방지하기 위해 TCP는 흐름 제어를 사용한다.
슬라이딩 윈도우(Sliding Window)
TCP는 슬라이딩 윈도우 방식을 통해 흐름 제어를 수행한다.
Window란, 한 번에 전송 가능한 데이터의 양이다.
수신자는 자신이 처리할 수 있는 만큼의 윈도우 크기(Window Size)를 송신자에게 알려주고,
송신자는 해당 크기만큼만 데이터를 전송한다.
이때 윈도우 크기는 고정이 아닌 동적 조절이 가능하다.
오류 제어 (Error Control)
네트워크 환경에서는 데이터가 유실되거나 손상될 가능성이 항상 존재한다.
TCP는 이러한 문제를 감지하고 정확하게 복구하기 위해 오류 제어 메커니즘을 제공한다.
오류가 발생한 시점 이후의 모든 데이터를 다시 전송하는 Go-Back-N 기법과 다르게
실제 TCP는 Selective Repeat 개념을 기반으로 하며,
SACK(Selective Acknowledgment)을 통해 손실된 데이터만 정확히 재전송한다.
Selective Repeat (선택적 재전송)의 경우 오류가 발생한 세그먼트만 재전송하고,
수신자는 순서가 어긋난 데이터도 버퍼에 저장한 이후 올바른 순서로 재조합하는 방식이다.
혼잡 제어 (Congestion Control)
데이터 손실이 항상 송신자나 수신자의 문제는 아니다.
네트워크 자체가 혼잡해져 패킷이 드롭될 수도 있다.
이때 무작정 재전송을 반복하면,
오히려 네트워크가 붕괴(Congestion Collapse) 될 수 있다.
그래서 TCP는 네트워크 혼잡 상태를 감지하면
송신 속도 자체를 줄이는 혼잡 제어를 수행한다.
혼잡 제어의 핵심 아이디어는 다음과 같다.
손실 발생이 발생하면, 이를 혼잡 신호로 판단하고
송신자가 전송량(cwnd)을 감소시킨다.
이후 네트워크가 안정되면 점진적으로 증가하는 방식을 사용한다.
대표적인 TCP 혼잡 제어 알고리즘은 다음과 같다.
- TCP Tahoe: Slow Start + Congestion Avoidance
- TCP Reno: Fast Retransmit + Fast Recovery 추가
- TCP New Reno: 다중 손실 개선
- TCP Cubic: 고속 네트워크 환경에 최적화
- Elastic TCP
이 중에서 우리는 TCP Tahoe와 Reno를 중심으로 살펴볼 것이다.
TCP 통신 과정
네트워크에서 데이터를 통째로 통신하는 경우는 거의 없다.
TCP 통신 역시 마찬가지이고, 다음과 같이 요약할 수 있다.
- 데이터 스트림에서 받은 데이터를 일정 단위로 분할
- 분할된 데이터 단위에 TCP 헤더를 붙여서 TCP 세그먼트를 생성
- TCP 세그먼트를 IP 데이터그램으로 변환 (IP 데이터그램은 인터넷 통신에 사용되는 데이터 패킷)
- IP 데이터그램을 수신 애플리케이션에 전송
Receiver Event
TCP 프로토콜의 receiver event에는 다음과 같이 4가지 상황이 있다.

- 기대 순서의 세그먼트가 도착하고, ACK 대기 없는 경우
- 다음 세그먼트를 기다리며 최대 500ms까지 delayed ACK
- 기대 순서의 세그먼트가 도착하고, 이미 ACK 대기 중인 세그먼트가 존재할 경우
- 두 세그먼트를 모두 포함하는 누적 ACK 즉시 전송
- 순서가 어긋난 세그먼트(예상보다 큰 시퀀스 번호)가 도착할 경우
- gap을 감지하고 다음 기대 바이트 번호를 담은 duplicate ACK 즉시 전송
- gap을 부분/전체적으로 채우는 세그먼트 도착할 경우
- gap의 시작 부분(lower end)부터 채우는 세그먼트이므로 즉시 ACK 전송

이 때 위 그림처럼 TCP 통신 도중 패킷 손실이 발생하는 경우,
GBN/SR 프로토콜과 마찬가지로 재전송 매커니즘이 동작한다.
재전송 매커니즘
타임아웃 재전송(Timeout Retransmit)
기본적으로 TCP는 cumulative ACK와 시퀀스 번호를 사용한다.
송신자는 보낸 데이터가 ACK로 확인되지 않으면 손실로 판단하고 재전송한다.
TCP도 GBN/SR과 동일하게 timer를 이용한 timeout 기반 재전송이 존재한다.
세그먼트를 보낼 때 RTT를 측정하고, 이를 기반으로 RTO(Retransmission Timeout)을 계산하여
설정된 RTO 안에 ACK가 도착하지 않으면 해당 세그먼트를 재전송한다.
이러한 방법은 손실을 확실히 감지할 수 있지만,
RTO가 크면 재전송이 늦어질 수 있다는 단점이 있다.
이를 보완하고자 실제 TCP 프로토콜에서는 Fast Retransmit도 혼합하여 사용한다.
중복 ACK 기반 재전송 (Fast Retransmit)
receiver가 순서가 어긋난 세그먼트를 받으면
마지막으로 정상 수신한 바이트 번호를 기반으로 ACK를 보낸다.
즉, 동일한 ACK가 반복적으로 송신자에게 도착하게 되고,
송신자가 같은 ACK를 3번 연속 수신하면
타임아웃을 기다리지 않고 손실된 세그먼트를 즉시 재전송하게 된다.
이를 통해 타임아웃보다 훨씬 빠르게 손실을 복구하고,
이는 고속 네트워크에서 매우 중요하다.
Fast Recovery (재전송 후 동작)
Fast Retransmit 이후 TCP는 네트워크에 혼잡이 발생했다고 가정하고
혼잡 윈도우(cwnd)를 절반으로 감소시키고, 재전송 세그먼트를 전송한다.
이후 중복 ACK 수신 시 cwnd를 조금씩 증가(선형 증가)시키고,
새로운 ACK 도착 시 혼잡 회피(Congestion Avoidence) 단계로 전환한다.
요약
