rust 데이터 프레이밍

wangki·2025년 8월 31일
0

Rust

목록 보기
49/54

개요

데이터 프레이밍이란?

이 기술을 사용하는 이유는 TCP 통신의 메시지 경계 문제를 해결하기 위해서이다.
TCP는 데이터 스트림을 연속적으로 전송하므로, 하나의 큰 데이터 덩어리를 여러 번에 나눠 보내거나, 여러 개의 작은 메시지가 합쳐져서 한 번에 도착할 수 있다.
LengthDelmitedCodec과 같은 데이터 프레이밍 기술은 이러한 문제를 해결하고, 메시지 단위로 안정적인 통신을 가능하게 한다.

TCP는 바이트의 연속적인 흐름일 뿐이므로, 한 메시지가 어디서 시작하고 어디서 끝나는지 알 수 없다.
프레이밍 기술은 각 메시지에 명확한 시작과 끝을 부여하여, 수신자가 완전한 하나의 메시지를 정확히 파싱하도록 한다.

Framed와 같은 래퍼는 개발자가 복잡한 바이트 레벨의 파싱 로직을 직접 구현할 필요 없이, send()next()같은 간단한 메서드로 메시지를 주고 받을 수 있게 해준다.

내용

LengthDelimitedCodec의 정확한 기능

LengthDelimitedCodec은 길이 접두사 프레이밍을 구현하는 코덱이다. 이 코덱은 데이터 스트림을 다룰 때, 두 가지 주요 기능을 수행한다.

  • 인코딩 (데이터 전송 시): 보낼 메시지를 받아서, 그 메시지의 총 길이를 나타내는 4바이트 값을 앞에 붙여준다. e.g. "Hello"라는 5바이트 메시지를 보내면, 코덱은 먼저 5를 나타내는 4바이트를 추가한 후, "Hello"바이트를 이어서 보낸다.
  • 디코딩 (데이터 수신 시): 스트림에서 들어오는 데이터를 읽을 때, 먼저 첫 4바이트를 읽어서 메시지의 길이를 파악한다. 그런 다음, 그 길이만큼의 바이트를 읽어서 완전한 메시지를 복원한다.
// server
pub async fn run_server() {
    let listener = TcpListener::bind("0.0.0.0:9999").await.unwrap();
    let Ok((mut stream, addr)) = listener.accept().await else {
        eprintln!("fail");
        return;
    };

    // TcpStream을 LengthDelimitedCodec으로 래핑
    let mut framed = Framed::new(stream, LengthDelimitedCodec::new());

    while let Some(result) = framed.next().await {
        match result {
            Ok(bytes) => {
                let message = String::from_utf8_lossy(&bytes);
                println!("수신: {}", message);
            }
            Err(e) => {
                eprintln!("통신 오류!: {}", e);
                break;
            }
        }
    }
}
// client
pub async fn run_client() {
    let Ok(mut stream) = TcpStream::connect("127.0.0.1:9999").await else {
        println!("fail to connect <127.0.0.1:9999>");
        return;
    };

    // 보낼 데이터 설정
    let send_data = vec!["안녕하세요", "만나서 반가워요", "잘 부탁드려요"];

    let mut framed = Framed::new(stream, LengthDelimitedCodec::new());

    for data in send_data {
        if let Err(e) = framed.send(Bytes::from(data)).await {
            eprintln!("메시지 전송 실패: {}", e);
        }
    }
}

결론

TCP통신을 할 때, 보낼 데이터의 길이를 먼저 보낸 후 데이터를 보내는 방식으로 프로토콜을 커스텀 하는게 흔하다.
데이터 프레이밍 기술은 위 방식을 추상화하여 개발자가 편하게 사용할 수 있고 실수 없이 안정적으로 구현해놓은 기능인 것 같다.

모든 기술은 장점이 있다면 그에 따르는 트레이드오프가 있다.
데이터 프레이밍 기술의 주요 단점은 아래와 같다고 한다.

  1. 추가적인 길이 정보만큼 데이터 오버헤드가 발생한다.
  2. 고정된 크기의 메시지만 주고받는 프로토콜이라면, 굳이 길이 정보를 붙이는 것이 불필요할 수 있다.
  3. 라이브러리 의존성이 생긴다.

위와 같은 트레이드오프가 존재한다고는 하지만 압도적으로 편리한 사용성과 유연성을 고려했을 때, 앞으로 rust에서 TCP 통신을 할 때 적극적으로 사용할 예정이다.

0개의 댓글