STUDY

[네트워크] TCP 신뢰성 보장 원리: 오류 제어, 흐름 제어, 혼잡 제어

sed 2026. 5. 28. 22:23
SMALL

TCP의 신뢰성 보장

TCP는 연결형 프로토콜이면서 신뢰성 있는 통신을 제공하는 전송 계층 프로토콜이다.

 

TCP는 데이터를 주고받기 전에 먼저 연결을 수립한다. 그리고 데이터 송수신이 끝나면 연결을 종료한다.

 

데이터를 주고받는 동안에는 신뢰성 있는 전송을 보장하기 위해 여러 기능을 제공한다.

 

대표적인 기능은 다음과 같다.

오류 제어
흐름 제어
혼잡 제어

 

오류 제어는 손상되거나 유실된 데이터를 다시 보내는 기능이다.

흐름 제어는 수신자가 처리할 수 있는 만큼만 데이터를 보내도록 조절하는 기능이다.

혼잡 제어는 네트워크가 혼잡한 정도에 따라 송신량을 조절하는 기능이다.

 

TCP가 신뢰성 있는 통신을 제공한다고 할 때, 그 핵심에는 이 세 가지 기능이 있다.

 

재전송 기반 오류 제어

TCP는 오류가 발생했을 때 세그먼트를 재전송하여 신뢰성을 확보한다.

 

TCP 세그먼트에는 체크섬 필드가 있다. 체크섬은 데이터가 전송 중에 훼손되었는지 확인하는 데 사용된다.

 

하지만 체크섬만으로는 충분하지 않다.

체크섬은 데이터가 손상되었는지는 확인할 수 있지만, 패킷 자체가 유실되었는지, 잘못된 순서로 도착했는지, 중간에 빠진 데이터가 있는지는 완전히 해결하지 못한다.

 

TCP가 신뢰성을 보장하려면 송신 호스트가 자신이 보낸 세그먼트에 문제가 생겼는지 알아야 한다. 문제가 생겼다고 판단하면 해당 세그먼트를 다시 보내야 한다.

 

TCP는 주로 두 가지 상황에서 오류를 감지하고 재전송한다.

중복 ACK를 수신했을 때
타임아웃이 발생했을 때

 

중복 ACK를 수신했을 때

수신 호스트는 데이터를 받으면 다음으로 받고 싶은 순서 번호를 ACK로 알려준다.

를 들어 수신자가 1번, 2번 세그먼트는 받았지만 3번 세그먼트를 받지 못했다고 하자. 그런데 4번, 5번 세그먼트가 먼저 도착하면 수신자는 계속 “3번을 기다리고 있다”는 ACK를 보낸다.

 

송신자는 같은 ACK가 반복해서 도착하는 것을 보고 특정 세그먼트가 중간에 빠졌다고 판단할 수 있다.

같은 ACK가 여러 번 도착하면 송신자는 해당 세그먼트가 유실되었을 가능성이 높다고 보고 재전송한다.

 

타임아웃이 발생했을 때

송신 호스트는 세그먼트를 보낼 때마다 재전송 타이머를 시작한다.

 

정해진 시간 안에 ACK가 오면 정상적으로 전달되었다고 판단한다.

 

하지만 타이머가 만료될 때까지 ACK가 오지 않으면 문제가 생겼다고 판단한다.

 

네트워크 중간에서 세그먼트가 유실되었거나, 수신자의 ACK가 유실되었을 때 타임아웃이 발생할 수 있다.

 

TCP는 이런 상황에서 해당 세그먼트를 다시 보낸다.

 

ARQ

TCP의 재전송 방식은 ARQ와 관련된다.

ARQ(Automatic Repeat Request)는 자동 재전송 요구를 의미한다.

 

수신자의 ACK와 타임아웃을 바탕으로 문제가 생겼는지 판단하고, 문제가 있는 데이터를 다시 보내 신뢰성을 확보하는 방식이다.

 

대표적인 ARQ 방식에는 다음 세 가지가 있다.

Stop-and-Wait ARQ
Go-Back-N ARQ
Selective Repeat ARQ

 

Stop-and-Wait ARQ

Stop-and-Wait ARQ는 하나를 보내고 확인을 받은 뒤 다음 것을 보내는 방식이다.

 

송신자는 세그먼트 하나를 보낸 뒤, 그 세그먼트가 제대로 도착했다는 ACK를 받을 때까지 기다린다.

 

ACK를 받으면 다음 세그먼트를 보낸다.

세그먼트 전송
ACK 대기
ACK 수신
다음 세그먼트 전송

 

이 방식은 단순하고 신뢰성이 높다.

 

하지만 성능이 좋지는 않다.

 

ACK를 기다리는 동안 송신자는 더 보낼 수 있어도 기다려야 한다. 수신자도 더 많은 데이터를 처리할 수 있는데 하나씩만 받게 된다.

 

네트워크를 충분히 활용하지 못하므로 전송 효율이 낮다.

 

파이프라이닝

Stop-and-Wait ARQ의 비효율을 줄이려면 ACK를 받기 전에도 여러 세그먼트를 연속해서 보낼 수 있어야 한다.

이처럼 여러 메시지를 연속해서 전송하는 기술을 파이프라이닝(pipelining)이라고 한다.

 

파이프라이닝을 사용하면 송신자는 여러 세그먼트를 한 번에 보내고, 수신자는 여러 세그먼트에 대한 ACK를 보낼 수 있다.

 

파이프라이닝 기반 ARQ에는 Go-Back-N ARQ와 Selective Repeat ARQ가 있다.

 

Go-Back-N ARQ

Go-Back-N ARQ는 여러 세그먼트를 연속해서 보내다가 오류가 발생하면, 문제가 발생한 세그먼트부터 뒤의 세그먼트를 모두 다시 보내는 방식이다.

 

예를 들어 1번부터 5번 세그먼트를 보냈는데 3번 세그먼트가 유실되었다고 하자.

 

수신자는 1번과 2번은 정상적으로 받았지만, 3번을 받지 못했다. 이후 4번과 5번이 도착하더라도 순서가 맞지 않으므로 정상 처리하지 않는다.

송신자는 3번부터 다시 보낸다.

1, 2 정상 수신
3 유실
4, 5 도착했지만 사용하지 않음
3, 4, 5 재전송

 

Go-Back-N ARQ에서는 ACK가 누적 확인 응답으로 동작한다.

누적 확인 응답은 특정 번호까지의 데이터를 모두 잘 받았다는 의미이다.

 

예를 들어 ACK 6은 “6번부터 보내면 된다”는 의미로 볼 수 있다. 다시 말해 5번까지는 정상적으로 받았다는 뜻이다.

 

이를 CACK(Cumulative Acknowledgment)라고 한다.

 

 

빠른 재전송

빠른 재전송(fast retransmit)은 타이머가 만료되기 전이라도 같은 ACK가 여러 번 반복되면 곧바로 재전송하는 방식이다.

일반적으로 같은 ACK를 3번 중복해서 받으면 송신자는 해당 세그먼트가 유실되었다고 보고 바로 재전송한다.

중복 ACK 3회 수신
타임아웃까지 기다리지 않음
해당 세그먼트 즉시 재전송

 

이 방식은 타임아웃까지 기다리는 시간을 줄일 수 있다.

 

Selective Repeat ARQ

Selective Repeat ARQ는 문제가 발생한 세그먼트만 선택적으로 재전송하는 방식이다.

 

Go-Back-N ARQ에서는 중간에 하나가 빠지면 그 뒤의 세그먼트까지 모두 다시 보내야 한다.

Selective Repeat ARQ에서는 정상적으로 받은 세그먼트는 유지하고, 유실되거나 오류가 발생한 세그먼트만 다시 요청한다.

1, 2 정상 수신
3 유실
4, 5 정상 수신
3만 재전송

 

 

Selective Repeat ARQ에서는 각 세그먼트에 대해 개별 ACK를 보낼 수 있다.

 

Go-Back-N ARQ의 ACK가 누적 확인 응답이라면, Selective Repeat ARQ의 ACK는 개별 확인 응답에 가깝다.

 

이를 SACK(Selective Acknowledgment)라고 부른다.

 

오늘날 대부분의 호스트는 SACK을 지원한다. SACK을 사용하지 않는 경우에는 Go-Back-N 방식에 가까운 동작을 할 수 있다.

 

흐름 제어

파이프라이닝을 사용하면 ACK를 기다리지 않고 여러 세그먼트를 보낼 수 있다.

하지만 무한히 많이 보낼 수는 없다.

 

수신 호스트가 한 번에 받아서 처리할 수 있는 양에는 한계가 있다. 송신자가 수신자의 처리 능력보다 더 많은 데이터를 보내면 수신 측 버퍼가 가득 차고, 데이터가 손실될 수 있다.

 

이를 막기 위한 기능이 흐름 제어(flow control)이다.

흐름 제어는 송신 호스트가 수신 호스트의 처리 능력을 고려하여 데이터를 보내도록 조절하는 기능이다.

수신자가 처리할 수 있는 만큼만 보낸다.
수신자의 버퍼를 넘치게 하지 않는다.

 

Stop-and-Wait ARQ에서는 하나 보내고 하나 확인받는 방식이므로 별도의 복잡한 흐름 제어가 크게 필요하지 않다.

 

하지만 Go-Back-N ARQ나 Selective Repeat ARQ처럼 여러 세그먼트를 연속해서 보내는 방식에서는 흐름 제어가 중요하다.

 

슬라이딩 윈도우

TCP의 대표적인 흐름 제어 기법은 슬라이딩 윈도우(sliding window)이다.

윈도우는 ACK를 받지 않고도 한 번에 보낼 수 있는 데이터의 범위를 의미한다.

 

수신 호스트는 자신이 한 번에 받아 처리할 수 있는 데이터 양을 TCP 헤더의 윈도우 필드에 담아 송신 호스트에게 알려준다.

 

송신 호스트는 이 값을 참고해 한 번에 보낼 수 있는 양을 정한다.

 

예를 들어 보낼 데이터가 길게 일렬로 있다고 하자.

 

그 데이터 위에 반투명한 종이를 올려둔다고 생각하면 된다. 이 종이 안에 들어온 데이터만 ACK를 기다리지 않고 한 번에 보낼 수 있다.

 

이 반투명한 종이의 크기가 윈도우 크기이다.

 

ACK가 도착하면 이미 확인된 데이터는 윈도우 밖으로 빠지고, 윈도우는 오른쪽으로 미끄러지듯 이동한다. 그래서 슬라이딩 윈도우라고 부른다.

앞의 데이터에 대한 ACK 수신
윈도우가 오른쪽으로 이동
새로운 데이터 전송 가능

 

송신 윈도우와 수신 윈도우

수신 호스트가 TCP 헤더의 윈도우 필드를 통해 알려주는 값은 수신 윈도우이다.

수신 윈도우는 수신자가 현재 받아들일 수 있는 데이터 양을 의미한다.

 

송신 호스트는 이 값을 바탕으로 자신의 송신 윈도우를 조절한다.

 

송신 윈도우는 송신자가 ACK를 기다리지 않고 보낼 수 있는 데이터 양이다.

수신 윈도우
수신자가 받아들일 수 있는 데이터 양

송신 윈도우
송신자가 한 번에 보낼 수 있는 데이터 양

 

송신자는 수신자가 감당할 수 있는 범위 안에서 데이터를 보내야 한다.

 

 

 

혼잡 제어

흐름 제어가 수신자의 처리 능력을 고려하는 기능이라면, 혼잡 제어는 네트워크 전체의 상태를 고려하는 기능이다.

혼잡(congestion)은 네트워크에 트래픽이 너무 많이 몰려 패킷 처리 속도가 느려지거나 패킷이 유실될 위험이 커진 상태이다.

 

예를 들어 하나의 라우터나 네트워크 장비에 너무 많은 트래픽이 몰리면 패킷이 지연되거나 버려질 수 있다.

 

혼잡 제어(congestion control)는 송신 호스트가 네트워크 혼잡 정도에 맞춰 전송량을 조절하는 기능이다.

 

흐름 제어의 기준은 수신 호스트이다.

혼잡 제어의 기준은 네트워크 상태이다.

흐름 제어
수신자가 감당할 수 있는 만큼 보낸다.

혼잡 제어
네트워크가 감당할 수 있는 만큼 보낸다.

 

혼잡 윈도우

TCP 혼잡 제어에서는 혼잡 윈도우(congestion window)라는 값을 사용한다.

혼잡 윈도우는 네트워크에 혼잡을 일으키지 않고 보낼 수 있을 것으로 예상되는 데이터 양이다.

 

혼잡 윈도우가 크면 한 번에 더 많은 세그먼트를 보낼 수 있다.

혼잡 윈도우가 작으면 한 번에 보낼 수 있는 세그먼트 수가 줄어든다.

 

수신 윈도우는 수신 호스트가 TCP 헤더를 통해 알려준다.

혼잡 윈도우는 송신 호스트가 네트워크 상황을 보며 직접 계산한다.

실제로 송신자가 한 번에 보낼 수 있는 양은 수신 윈도우와 혼잡 윈도우를 함께 고려해 정해진다.

AIMD

혼잡 제어의 기본적인 아이디어 중 하나가 AIMD(Additive Increase Multiplicative Decrease)이다.

AIMD는 더할 때는 조금씩 늘리고, 줄일 때는 크게 줄이는 방식이다.

 

혼잡이 감지되지 않으면 혼잡 윈도우를 RTT마다 조금씩 증가시킨다.

혼잡이 감지되면 혼잡 윈도우를 크게 줄인다. 보통 절반으로 줄이는 방식으로 설명된다.

 

RTT(Round Trip Time)는 메시지를 보낸 뒤 그에 대한 응답을 받기까지 걸리는 시간이다.

AIMD는 조심스럽게 전송량을 늘리다가, 혼잡이 감지되면 빠르게 줄이는 방식이다.

느린 시작

느린 시작(slow start)은 TCP 연결 초기에 혼잡 윈도우를 빠르게 키우는 알고리즘이다.

이름은 느린 시작이지만 실제로는 초기에 전송량을 지수적으로 증가시킨다.

 

처음에는 혼잡 윈도우를 1 MSS에서 시작한다. 이후 ACK를 정상적으로 받을 때마다 혼잡 윈도우를 늘린다.

 

결과적으로 RTT마다 혼잡 윈도우가 약 2배씩 증가한다.

 

처음부터 많은 데이터를 보내면 네트워크가 감당할 수 있는지 알 수 없다.

그래서 작은 값에서 시작하되, 문제가 없으면 빠르게 전송량을 키운다.

 

 

느린 시작 임계치

느린 시작은 계속 무한히 증가하지 않는다.

느린 시작 임계치(slow start threshold)라는 기준이 있다.

 

혼잡 윈도우가 이 임계치에 도달하면 느린 시작을 끝내고 혼잡 회피 단계로 넘어간다.

 

느린 시작 중에는 크게 세 가지 상황이 발생할 수 있다.

혼잡 윈도우가 느린 시작 임계치 이상이 된 경우
타임아웃이 발생한 경우
중복 ACK가 3번 발생한 경우

 

타임아웃이 발생하면 혼잡이 심각하다고 판단한다.

 

이때 혼잡 윈도우를 1로 줄이고, 느린 시작 임계치를 혼잡이 감지된 시점의 혼잡 윈도우 절반으로 설정한 뒤 다시 느린 시작을 수행한다.

 

혼잡 윈도우가 느린 시작 임계치 이상이 되면 느린 시작을 끝내고 혼잡 회피를 수행한다.

 

중복 ACK가 3번 발생하면 빠른 재전송을 수행하고, 빠른 회복 단계로 넘어갈 수 있다.

 

혼잡 회피

혼잡 회피(congestion avoidance)는 혼잡 윈도우를 조심스럽게 증가시키는 알고리즘이다.

 

느린 시작에서는 혼잡 윈도우가 지수적으로 증가한다.

 

혼잡 회피에서는 RTT마다 혼잡 윈도우를 1 MSS 정도씩 증가시킨다.

 

느린 시작 임계치를 넘었다는 것은 네트워크가 혼잡해질 가능성이 커졌다는 의미로 볼 수 있다.

그래서 이 시점부터는 전송량을 급격히 늘리지 않고 조심스럽게 증가시킨다.

 

 


빠른 회복

빠른 회복(fast recovery)은 중복 ACK가 3번 발생했을 때 느린 시작을 건너뛰고 혼잡 회피로 이어지는 방식이다.

타임아웃은 비교적 심각한 혼잡 신호로 본다.

 

반면 중복 ACK 3회는 일부 세그먼트가 유실되었지만, 이후 세그먼트나 ACK는 계속 오고 있다는 뜻일 수 있다. 네트워크가 완전히 막힌 상황은 아닐 가능성이 있다.

 

그래서 중복 ACK 3회가 발생하면 빠른 재전송을 하고, 혼잡 윈도우를 1로 완전히 낮추기보다 빠른 회복을 통해 전송률을 비교적 빠르게 회복한다.

 

빠른 회복 중에도 타임아웃이 발생하면 더 심각한 혼잡으로 보고 다시 느린 시작을 수행한다.

 

LIST