TCP 신뢰성 전송
우리는 모두 TCP 프로토콜을 안정적인 전송 프로토콜로 알고 있지만, 이 프로토콜은 어떻게 전송의 안정성을 보장할까요?
안정적인 전송을 위해서는 데이터 손상, 손실, 중복, 샤드 순서 오류 등 여러 요소를 고려해야 합니다. 이러한 문제를 해결하지 못하면 안정적인 전송을 달성할 수 없습니다.
따라서 TCP는 시퀀스 번호, 확인 응답, 재전송 제어, 연결 관리, 윈도우 제어와 같은 메커니즘을 사용하여 안정적인 전송을 달성합니다.
본 논문에서는 TCP의 슬라이딩 윈도우, 흐름 제어, 그리고 혼잡 제어에 중점을 두고, 재전송 메커니즘은 다음 절에서 별도로 설명합니다.
네트워크 흐름 제어
네트워크 흐름 제어(Network Flow Control) 또는 네트워크 트래픽 제어(Network Traffic Control)는 실제로 생산자와 소비자 간의 미묘한 관계를 나타냅니다. 직장이나 면접에서 이러한 상황을 많이 접해 보셨을 것입니다. 생산자의 생산 용량이 소비자의 소비 용량을 크게 초과하면 대기열이 무한정 증가합니다. 더 심각한 경우, RabbitMQ 메시지가 너무 많이 쌓이면 전체 MQ 서버의 성능 저하를 초래할 수 있습니다. TCP도 마찬가지입니다. 제대로 관리하지 않으면 너무 많은 메시지가 네트워크에 유입되어 소비자는 용량을 초과하게 되고, 생산자는 중복 메시지를 계속 보내 네트워크 성능에 큰 영향을 미칩니다.
이러한 현상을 해결하기 위해 TCP는 송신자가 수신자의 실제 수신 용량에 따라 전송되는 데이터 양을 제어할 수 있는 메커니즘을 제공하는데, 이를 흐름 제어라고 합니다. 수신자는 수신 윈도우를 유지하고, 송신자는 송신 윈도우를 유지합니다. 이러한 윈도우는 단일 TCP 연결에만 적용되며 모든 연결이 윈도우를 공유하는 것은 아니라는 점에 유의해야 합니다.
TCP는 수신 윈도우 변수를 사용하여 흐름 제어를 제공합니다. 수신 윈도우는 송신자에게 남은 캐시 공간을 알려줍니다. 송신자는 수신자의 실제 수용 용량에 따라 전송되는 데이터 양을 제어합니다.
수신 호스트는 송신자에게 수신 가능한 데이터 크기를 알리고, 송신자는 이 제한값까지 데이터를 전송합니다. 이 제한값이 바로 윈도우 크기입니다. TCP 헤더를 기억하시나요? 수신자가 수신할 수 있거나 수신하려는 바이트 수를 나타내는 수신 윈도우 필드가 있습니다.
송신 호스트는 수신 호스트가 데이터를 수신할 수 있는지 여부를 감지하는 데 사용되는 윈도우 프로브 패킷을 주기적으로 전송합니다. 수신 버퍼가 오버플로우될 위험이 있는 경우, 송신 호스트가 전송되는 데이터 양을 제어하도록 윈도우 크기를 더 작은 값으로 설정합니다.
네트워크 흐름 제어 다이어그램은 다음과 같습니다.
네트워크 혼잡 제어
혼잡 제어를 도입하기 전에, 수신 윈도우와 송신 윈도우 외에도 송신자가 수신 윈도우로 데이터를 전송하기 시작하는 속도 문제를 해결하는 데 주로 사용되는 혼잡 윈도우가 있다는 점을 이해해야 합니다. 따라서 혼잡 윈도우는 TCP 송신자에서도 유지됩니다. 너무 적거나 너무 많은 데이터를 전송하는 것은 바람직하지 않으므로, 적절한 데이터 양을 결정하는 알고리즘이 필요합니다. 바로 이러한 이유로 혼잡 윈도우라는 개념이 등장하게 되었습니다.
이전 네트워크 흐름 제어에서는 송신자가 수신자의 캐시에 데이터를 채우는 것을 방지했지만, 네트워크에서 어떤 일이 일어나는지 알 수 없었습니다. 일반적으로 컴퓨터 네트워크는 공유 환경에 있습니다. 따라서 다른 호스트 간의 통신으로 인해 네트워크 혼잡이 발생할 수 있습니다.
네트워크가 혼잡할 때 대량의 패킷이 지속적으로 전송되면 지연 및 패킷 손실과 같은 문제가 발생할 수 있습니다. 이 시점에서 TCP는 데이터를 재전송하지만, 재전송은 네트워크 부하를 증가시켜 더 큰 지연과 더 많은 패킷 손실을 초래합니다. 이는 악순환에 빠져 점점 더 심각해질 수 있습니다.
따라서 TCP는 네트워크에서 발생하는 상황을 무시할 수 없습니다. 네트워크가 혼잡해지면 TCP는 전송하는 데이터 양을 줄임으로써 스스로를 희생합니다.
따라서 송신자의 데이터로 전체 네트워크가 가득 차는 것을 방지하기 위한 혼잡 제어가 제안됩니다. 송신자가 전송해야 하는 데이터 양을 조절하기 위해 TCP는 혼잡 윈도우라는 개념을 정의합니다. 혼잡 제어 알고리즘은 네트워크의 혼잡도에 따라 혼잡 윈도우 크기를 조절하여 송신자가 전송하는 데이터 양을 제어합니다.
혼잡 윈도우란 무엇인가요? 전송 윈도우와 어떤 관련이 있나요?
혼잡 윈도우는 송신자가 관리할 수 있는 상태 변수로, 송신자가 전송할 수 있는 데이터 양을 결정합니다. 혼잡 윈도우는 네트워크의 혼잡 수준에 따라 동적으로 변경됩니다.
송신 윈도우는 송신자와 수신자가 합의한 윈도우 크기로, 수신자가 수신할 수 있는 데이터 양을 나타냅니다. 혼잡 윈도우와 송신 윈도우는 서로 연관되어 있으며, 송신 윈도우는 일반적으로 혼잡 윈도우와 수신 윈도우의 최소값, 즉 swnd = min(cwnd, rwnd)과 같습니다.
혼잡 창 cwnd는 다음과 같이 변경됩니다.
네트워크에 혼잡이 없다면, 즉 재전송 시간 초과가 발생하지 않는다면 혼잡 윈도우는 늘어납니다.
네트워크에 혼잡이 발생하면 혼잡 창은 줄어듭니다.
송신자는 지정된 시간 내에 ACK 확인 패킷이 수신되는지 여부를 관찰하여 네트워크 혼잡 여부를 판단합니다. 송신자가 지정된 시간 내에 ACK 확인 패킷을 수신하지 못하면 네트워크 혼잡으로 간주됩니다.
혼잡 윈도우 외에도 TCP 혼잡 제어 알고리즘에 대해 알아보겠습니다. TCP 혼잡 제어 알고리즘은 세 가지 주요 부분으로 구성됩니다.
느린 시작:초기에는 cwnd 혼잡 윈도우가 비교적 작으며, 송신자는 네트워크 용량에 빠르게 적응하기 위해 혼잡 윈도우를 기하급수적으로 늘립니다.
혼잡 회피:혼잡 윈도우가 특정 임계값을 초과하면, 송신자는 혼잡 윈도우를 선형적으로 늘려 혼잡 윈도우의 성장률을 늦추고 네트워크 과부하를 방지합니다.
빠른 복구:혼잡이 발생하면 송신자는 혼잡 윈도우를 절반으로 줄이고 빠른 복구 상태로 전환하여 수신된 중복 ack를 통해 네트워크 복구 위치를 파악한 후 계속해서 혼잡 윈도우를 늘립니다.
느린 시작
TCP 연결이 설정되면 혼잡 윈도우(cwnd)는 초기에 최소 MSS(최대 세그먼트 크기) 값으로 설정됩니다. 이렇게 하면 초기 전송 속도는 약 MSS/RTT 바이트/초가 됩니다. 실제로 사용 가능한 대역폭은 일반적으로 MSS/RTT보다 훨씬 크기 때문에 TCP는 최적의 전송 속도를 찾으려고 하며, 이는 슬로우 스타트를 통해 달성할 수 있습니다.
슬로우 스타트 프로세스에서 혼잡 윈도우(cwnd) 값은 1 MSS로 초기화되고, 전송된 패킷 세그먼트가 확인응답될 때마다 cwnd 값이 1 MSS씩 증가합니다. 즉, cwnd 값은 2 MSS가 됩니다. 그 후, 패킷 세그먼트가 성공적으로 전송될 때마다 cwnd 값은 두 배로 증가합니다. 구체적인 증가 과정은 다음 그림과 같습니다.
하지만 전송 속도가 항상 증가하는 것은 아닙니다. 증가는 언젠가는 끝나야 합니다. 그렇다면 전송 속도 증가는 언제 끝날까요? 슬로우 스타트는 일반적으로 다음 중 한 가지 방법으로 전송 속도 증가를 끝냅니다.
첫 번째 방법은 슬로우 스타트 전송 과정에서 패킷 손실이 발생하는 경우입니다. 패킷 손실이 발생하면 TCP는 송신자의 혼잡 윈도우(cwnd)를 1로 설정하고 슬로우 스타트 프로세스를 다시 시작합니다. 이때, 패킷 손실을 유발하는 cwnd 값의 절반인 슬로우 스타트 임계값(ssthresh)이 도입됩니다. 즉, 혼잡이 감지되면 ssthresh 값은 윈도우 값의 절반이 됩니다.
두 번째 방법은 슬로우 스타트 임계값 ssthresh와 직접 연관시키는 것입니다. 혼잡 감지 시 ssthresh 값은 윈도우 값의 절반이므로, cwnd가 ssthresh보다 클 경우 두 배로 증가할 때마다 패킷 손실이 발생할 수 있습니다. 따라서 cwnd를 ssthresh로 설정하는 것이 가장 좋습니다. 이렇게 하면 TCP가 혼잡 제어 모드로 전환되고 슬로우 스타트가 종료됩니다.
슬로우 스타트가 종료될 수 있는 마지막 방법은 세 개의 중복 ACK가 감지될 경우, TCP가 빠른 재전송을 수행하고 복구 상태로 전환하는 것입니다. (ACK 패킷이 세 개 있는 이유가 명확하지 않은 경우, 재전송 메커니즘에서 별도로 설명하겠습니다.)
혼잡 회피
TCP가 혼잡 제어 상태로 전환되면 cwnd는 혼잡 임계값 ssthresh의 절반으로 설정됩니다. 즉, 패킷 세그먼트가 수신될 때마다 cwnd 값을 두 배로 늘릴 수 없습니다. 대신, 각 전송이 완료된 후 cwnd 값을 최대 패킷 세그먼트 길이(MSS) 1개만큼만 증가시키는 비교적 보수적인 접근 방식을 채택합니다. 예를 들어, 10개의 패킷 세그먼트가 확인 응답을 받더라도 cwnd 값은 MSS 1개만큼만 증가합니다. 이는 선형 증가 모델이며 증가에 대한 상한값도 있습니다. 패킷 손실이 발생하면 cwnd 값이 MSS로 변경되고 ssthresh 값은 cwnd의 절반으로 설정됩니다. 또는 3개의 중복 ACK 응답이 수신되면 MSS 증가를 중지합니다. cwnd 값을 반으로 줄인 후에도 3개의 중복 ACK가 계속 수신되면 ssthresh 값을 cwnd 값의 절반으로 기록하고 빠른 복구 상태로 전환됩니다.
빠른 복구
빠른 복구 상태에서는 수신된 중복 ACK(즉, 순서대로 도착하지 않은 ACK)마다 혼잡 윈도우(cwnd) 값이 MSS 1씩 증가합니다. 이는 네트워크에서 성공적으로 전송된 패킷 세그먼트를 활용하여 전송 효율을 최대한 향상시키기 위한 것입니다.
손실된 패킷 세그먼트에 대한 ACK가 도착하면 TCP는 cwnd 값을 감소시키고 혼잡 회피 상태로 전환합니다. 이는 혼잡 윈도우 크기를 제어하고 네트워크 혼잡이 더 심화되는 것을 방지하기 위한 것입니다.
혼잡 제어 상태 이후 타임아웃이 발생하면 네트워크 상태가 더욱 심각해지고 TCP는 혼잡 회피 상태에서 슬로우 스타트 상태로 전환됩니다. 이 경우, 혼잡 윈도우(cwnd) 값은 최대 패킷 세그먼트 길이인 1 MSS로 설정되고, 슬로우 스타트 임계값(ssthresh)은 cwnd의 절반으로 설정됩니다. 이는 네트워크가 복구된 후 혼잡 윈도우 크기를 점진적으로 증가시켜 전송 속도와 네트워크 혼잡도의 균형을 맞추기 위한 것입니다.
요약
TCP는 안정적인 전송 프로토콜로서 시퀀스 번호, 확인응답, 재전송 제어, 연결 관리 및 윈도우 제어를 통해 안정적인 전송을 구현합니다. 이 중 흐름 제어 메커니즘은 수신자의 실제 수신 용량에 따라 송신자가 전송하는 데이터 양을 제어하여 네트워크 혼잡 및 성능 저하 문제를 방지합니다. 혼잡 제어 메커니즘은 송신자가 전송하는 데이터 양을 조절하여 네트워크 혼잡 발생을 방지합니다. 혼잡 윈도우와 전송 윈도우의 개념은 서로 연관되어 있으며, 송신자의 데이터 양은 혼잡 윈도우의 크기를 동적으로 조절하여 제어합니다. 느린 시작, 혼잡 회피, 빠른 복구는 TCP 혼잡 제어 알고리즘의 세 가지 주요 부분으로, 네트워크의 용량과 혼잡 정도에 적응하기 위해 다양한 전략을 통해 혼잡 윈도우의 크기를 조절합니다.
다음 섹션에서는 TCP의 재전송 메커니즘을 자세히 살펴보겠습니다. 재전송 메커니즘은 TCP에서 안정적인 전송을 위한 중요한 요소입니다. 손실, 손상 또는 지연된 데이터를 재전송하여 데이터의 안정적인 전송을 보장합니다. 다음 섹션에서는 재전송 메커니즘의 구현 원리와 전략을 소개하고 자세히 분석할 예정입니다. 기대해 주세요!
게시 시간: 2025년 2월 24일