CS/Computer Network

[컴퓨터네트워크/Computer Network] 신뢰적인 데이터 전송 원리 완벽 정리 (rdt 1.0 ~ 2.2)

binaryroot 2026. 5. 5. 15:48
728x90

이번 글에서는 네트워크 레이어 중 전송 계층(Transport Layer)의 핵심 기능 중 하나인 Principles of Reliable Data Transfer(rdt, 실뢰적인 데이터 전송 원리)에 대해 정리해보고자 한다.

 

데이터를 보낼 때 중간에 패킷이 손실되거나 에러가 발생하지 않도록 보장하는 것은 매우 중요하다. 하지만 우리가 사용하는 하위 네트워크 계층 (IP 등)은 기본적으로 Unreliable channel(비신뢰적 채널)이기 때문에, 전송 계층에서는 이를 극복하기 위한 복잡한 매커니즘이 요구된다. 

 

신뢰적인 데이터 전송

우리가 구현하고자하는 서비스의 추상적인 구조는 다음과 같다.

신뢰적인 데이터 전송

  • Reliable service abstraction (신뢰적인 서비스 추상화)
    상위 애플리케이션 계층에서는 데이터가 안전하게 전달된다고 믿고 데이터를 보낸다.
  • Reliable service implementation (신뢰적인 서비스 구현) 
    실제 밑바닥인 네트워크 계층은 사실 비신뢰적이다. 그렇기 때문에 전송 계층에서 rdt protocol (신뢰적인 데이터 전송 프로토콜)을 통해 데이터의 신뢰성을 보장해 주어야 한다.

데이터 전송을 위해 다음과 같은 함수들이 사용된다.

데이터 전송시 사용되는 함수

 

  • rdt_send() : 상위 계층(앱)이 데이터를 하위 계층으로 보내달라고 호출할 때 사용
  • udt_send() : 실제 비신뢰적인 채널(Unreliable channel)을 통해 패킷을 전송할 때 사용
  • deliver_data() : 수신 측에서 데이터를 상위 계층으로 전달할 때 사용
  • rdt_rcv() : 패킷이 수신 측에 도착했을 때 호출됨

 

rdt 1.0 : 신뢰적인 채널 상의 신뢰적 데이터 전송

가장 완벽한 세상인 rdt 1.0 부터 시작을 해보자. 여기서는 perfectly reliable channel (완벽하게 신뢰적인 채널)을 가정한다. 

즉, 비트 에러는 물론이고 패킷 손실도 없는 상태이다. 

  • Sender (송신자) : 상위 계층에서 데이터를 받아 패킷을 만들고 전송하기만 하면 된다.
  • Receiver (수신자) : 하위 계층에서 패킷을 받아 데이터를 추출해 상위 계층으로 전달한다.
  • 에러가 없기 때문에 별도의 제어 로직이 필요 없다는 것이 특징이다. 

rdt 2.0 : 비트 에러가 있는 채널 (Bit Errors)

rdt 1.0은 비현실적이기 때문에 현실적인 문제인 Bit Errors (비트 에러)를 고려해보자. 패킷을 전달되지만, 그 속의 내용이 전송 중에 바뀔 수 있다는 것이 가정이다.

 

이를 해결하기 위해 Stop-and-Wait protocol (전송 후 대기 프로토콜) 방식과 몇 가지 새로운 매커니즘이 도입된다.

rdt 2.0

 

핵심 매커니즘은 다음과 같다.

  1. Error detection (오류 검출) : 패킷이 깨졌는지 확인하기 위해 Checksum 을 사용한다.
  2. Receiver feedback (수신자 피드백)
    - ACK (Positive acknowledgment) : "잘 받았음."이라고 알려주는 응답
    - NAK (Negative aknowledgment) : "에러 존재. 다시 전송 필요."라고 알려주는 응답

rdt 2.0의 문제점

만약 송신자에게 돌아오는 ACK이나 NAK 자체가 깨져서 (corrupted) 도착한다면, 송신자는 수신자가 데이터를 잘 받았는지 알 수없는 상태가 되어버린다. 

728x90

rdt 2.1 : 깨진 ACK/NAK 처리하기

rdt 2.0의 치명적인 결함을 해결하기 위해서 rdt 2.1이 등장한다. 

rdt 2.1의 핵심은 송신자가 보낸 패킷에 번호를 붙이는 것이다.

rdt 2.1 송신자, 수신자

 

rdt 2.0과 비교하여 rdt 2.1의 변경사항은 다음과 같다.

  • Sequence numbers (순서 번호) : 각 패킷에 0 또는 1이라는 번호를 붙여서 보낸다.
  • 만약 ACK/NAK이 깨졌다면, 송신자는 retransmit(재전송)한다.
  • 수신자는 이미 받은 패킷(번호가 같은 패킷)이 다시 오면, 그것이 재전송된 것임을 알아차리고 데이터 중복 처리가 아닌, 버린 뒤 다시 ACK을 보낸다.

 

rdt 2.1은 ACK과 NAK을 모두 사용하였지만, NAK을 사용하지 않고도 같은 기능을 수행할 수 있는 프로토콜이 존재한다.

rdt 2.2 : NAK-free Protocol (NAK 없는 프로토콜)

rdt 2.2

 

  • 수신자는 마지막으로 성공적으로 받은 패킷의 번호를 포함하여 ACK을 보낸다.
    • 예) 패킷 0을 잘 받았다면 ACK 0 을 보낸다.
  • 만약 패킷 1을 보냈는데 에러가 났다면, 수신자는 다시 ACK 0을 보낸다.
    (가장 최근에 성공한 것이 0번 이기 때문)
  • 송신자 입장에서는 똑같은 번호의 Duplicate ACK (중복 ACK)를 받게 되면,
    '다음에 보낸 패킷이 제대로 전송되지 않음'을 알고 재전송을 수행할 수가 있게 된다.

 

 

지금까지 rdt 1.0부터 2.2까지 살펴보며, 비트 에러 (Bit Errors)가 발생하는 비신뢰적인 채널에서 어떻게 신뢰성을 구축해 나가는지에 대해 정리해보았다. Checksum, Sequence Number, 그리고 ACK 이라는 강력한 도구들을 통해 데이터가 깨지거나 중복되는 문제를 해결할 수 있게 되었다.

하지만 패킷 유실(Packet Loss) 문제가 발생한다면 어떻게 해야할 지에 대해서는 잘 모른다.

보낸 패킷이나 받아야할 ACK이 네트워크 어딘가에서 증발해 버리는 문제에 대해서 말이다.

 

다음 글에서는 타이머 (Timer)를 도입하여 이 유실 문제까지 해결하는 rdt 3.0에 대해서 정리해 보고자 한다.

728x90