Rust로 CLI 도구 만들며 배운 소유권 시스템

배경

매일 수백 MB의 서버 로그를 파싱하는 Python 스크립트가 있었다. 실행 시간이 2분 정도 걸렸고, 메모리도 1GB 이상 사용했다. Rust를 배운 김에 실전 프로젝트로 삼아 재작성해봤다.

첫 번째 벽: Borrow Checker

가장 먼저 마주친 문제는 소유권이었다. 로그 라인을 파싱한 결과를 여러 함수에서 참조해야 했는데, 계속 컴파일 에러가 났다.

fn parse_line(line: String) -> LogEntry {
    // line을 소비해버림
}

fn main() {
    let line = read_line();
    let entry = parse_line(line);
    println!("{}", line); // 에러: line이 이동됨
}

해결책은 참조자를 사용하는 것이었다.

fn parse_line(line: &str) -> LogEntry {
    // 참조만 받음
}

Lifetime 표기

구조체에 문자열 슬라이스를 저장하려니 lifetime 표기가 필요했다.

struct LogEntry<'a> {
    timestamp: &'a str,
    message: &'a str,
}

처음엔 번거로웠지만, 컴파일러가 메모리 안전성을 보장해주니 런타임 에러 걱정이 없었다.

결과

  • 실행 시간: 2분 → 8초
  • 메모리 사용: 1GB → 50MB
  • 바이너리 크기: 2MB (Python 인터프리터 불필요)

clap으로 CLI 인터페이스를 만들고, rayon으로 병렬 처리를 추가하니 더 빨라졌다.

배운 점

Rust의 학습 곡선은 가팔랐지만, 컴파일만 되면 거의 확실하게 동작했다. 특히 리팩토링 시 타입 시스템이 큰 도움이 됐다. 프로덕션에 투입하기엔 아직 이르지만, 도구 제작용으론 충분히 실용적이었다.