Rust로 CLI 도구 만들어보기 - Node.js 대비 실행 속도

배경

사내에서 쓰는 프로젝트 템플릿 생성 CLI가 있었다. Node.js로 작성되어 있었는데, 실행할 때마다 node_modules 포함해서 100MB가 넘는 용량이 문제였다. 설치 시간도 오래 걸리고, CI에서 캐시 미스 나면 매번 수 분씩 소요됐다.

Rust로 재작성하면 단일 바이너리로 배포할 수 있고, 실행 속도도 빠를 것 같아서 시도해봤다.

구현

기본적인 파일 복사, 템플릿 변수 치환 기능만 필요했다. clap 크레이트로 CLI 파싱, handlebars로 템플릿 처리, walkdir로 파일 순회 구조로 작성했다.

use clap::{App, Arg};
use std::fs;
use walkdir::WalkDir;

fn main() {
    let matches = App::new("project-init")
        .arg(Arg::with_name("name")
            .required(true)
            .index(1))
        .get_matches();
    
    let project_name = matches.value_of("name").unwrap();
    
    for entry in WalkDir::new("./template") {
        let entry = entry.unwrap();
        // 파일 복사 및 템플릿 처리 로직
    }
}

소유권 개념 때문에 초반에 컴파일 에러가 많이 났다. String과 &str 구분, 라이프타임 이해하는데 시간이 걸렸다.

결과

  • 빌드된 바이너리: 3.2MB (릴리즈 모드)
  • 실행 속도: Node.js 버전 대비 약 8배 빠름
  • 설치: 단일 파일 복사로 끝

CI 파이프라인에서 캐시 없이도 바로 실행 가능해져서 평균 2분 단축됐다.

소감

러닝커브가 있지만, 성능이 중요한 CLI 도구는 Rust로 작성할 만하다. 다만 빠른 프로토타이핑이 필요하면 여전히 Node.js가 낫다. 컴파일 시간도 꽤 걸리는 편이라 개발 사이클이 느려진다.

당분간은 성능 critical한 부분만 선택적으로 적용할 예정이다.