hyunsu blog

홈강좌Rust 실무 16편 중 2편째

Rust 의 단점 — 고르면 무엇을 치르나

목차 · 5
  1. 011. 컴파일이 오래 걸린다
  2. 022. 디스크를 많이 쓴다
  3. 033. 실행 파일이 커진다
  4. 044. 배우는 데 시간이 든다
  5. 05실습 — 언제 피하는 편이 나은가

Rust 를 고르면 컴파일 시간·디스크·배우는 시간을 치른다. 작은 axum 웹 서버 하나가 처음 빌드에 크레이트 48개를 컴파일하며 11초, target 폴더 173MB 를 썼다. 1.0 이 안 된 크레이트도 많다. 이 편은 그 값을 직접 재고, 언제 Rust 를 피하는 편이 나은지 기준을 정리한다.

01 1. 컴파일이 오래 걸린다

7편에서 만들 axum 웹 서버의 뼈대를 처음부터 빌드했다. 코드는 몇 줄뿐이다.

rust
use axum::{Router, routing::get};

#[tokio::main]
async fn main() {
    let app: Router = Router::new().route("/", get(|| async { "hello" }));
    let listener = tokio::net::TcpListener::bind("127.0.0.1:7878").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}
toml
[package]
name = "web"
version = "0.1.0"
edition = "2024"

[dependencies]
axum = "=0.8.9"
tokio = { version = "=1.54.1", features = ["rt-multi-thread", "macros", "net"] }
bash
cargo build
touch src/main.rs
cargo build
text
   Compiling hyper-util v0.1.21
   Compiling axum v0.8.9
   Compiling web v0.1.0 (~/projects/web)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 8.62s
   Compiling web v0.1.0 (~/projects/web)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.34s

위로 Compiling 이 48줄 더 있다. 우리가 적은 의존성은 둘(axum·tokio)이지만, 그것들이 쓰는 크레이트까지 모두 소스에서 컴파일한다. 처음 빌드가 8~11초다(실행마다 조금 다르다). 다행히 한 번 컴파일한 크레이트는 다시 컴파일하지 않는다. 코드를 고치고(touch 로 고친 척을 했다) 다시 빌드하면 우리 크레이트만 컴파일해서 0.34초다.

프로젝트가 커지면 처음 빌드는 몇 분이 되기도 한다. CI 서버처럼 매번 깨끗한 곳에서 빌드하면 이 값을 매번 치른다. 그래서 CI 에서는 target 폴더를 캐시해 두는 것이 보통이다.

02 2. 디스크를 많이 쓴다

text
   Compiling axum v0.8.9
   Compiling web v0.1.0 (~/projects/web)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 11.45s
173M	target

debug 빌드 한 번에 target 폴더가 173MB 가 됐다. 중간 결과물과 디버그 정보를 모두 남기기 때문이다. release 빌드를 하면 따로 또 쌓인다. 프로젝트가 여럿이면 노트북 디스크가 금방 찬다. cargo clean 으로 지울 수 있고, 다음 빌드가 다시 처음부터라는 것만 감수하면 된다.

03 3. 실행 파일이 커진다

1편의 hello 는 431,200바이트였다. 같은 웹 서버를 release 로 빌드하면 이렇다.

text
   Compiling web v0.1.0 (~/projects/web)
    Finished `release` profile [optimized] target(s) in 9.51s
 1541600

1,541,600바이트(약 1.5MB)다. 의존하는 크레이트를 모두 실행 파일 안에 넣기(정적 링크) 때문이다. 대신 1편에서 본 대로 이 파일 하나만 있으면 돈다. 크기를 더 줄이는 설정(strip·opt-level = "z"·lto)은 Cargo Book 의 Profiles 장에 있다.

04 4. 배우는 데 시간이 든다

소유권·빌림·수명(입문 15~19·35편)은 다른 언어에 없는 개념이라, 처음 몇 주는 컴파일러와 씨름하는 시간이 길다. 컴파일러가 막는 것은 대부분 실제 버그지만, 이미 다른 언어로 잘 돌던 설계(예: 객체끼리 서로를 가리키는 구조)를 그대로 옮기면 잘 안 된다. 설계를 Rust 식으로 바꾸는 데 시간이 든다.

생태계는 빠르게 크지만 젊다. 이 편의 axum 은 0.8.9 다. 1.0 미만 크레이트는 0.8 → 0.9 처럼 가운데 숫자가 바뀔 때 기존 코드가 깨질 수 있다. 버전을 정확히 고정하고(입문 41편) Cargo.lock 을 저장소에 넣어 두는 습관이 필요하다.

05 실습 — 언제 피하는 편이 나은가

이런 때는이유
오늘 만들어 이번 주에 버릴 시제품컴파일러와 씨름할 시간이 아깝다. 스크립트 언어가 빠르다
데이터를 이리저리 살펴보는 분석노트북·인터프리터의 즉시 실행이 더 맞다
팀에 Rust 를 아는 사람이 없고 마감이 촉박배우는 시간이 일정에 그대로 얹힌다
이미 GC 언어로 충분히 빠르고 안정적옮기는 비용만 생긴다

반대로 오래 돌아야 하고, 지연이 튀면 안 되고, 메모리 오류가 사고로 이어지는 곳이라면 위의 값을 치를 만하다. 그런 곳이 실제로 어디인지는 다음 편에서 본다. 자기 프로젝트에서 cargo build 를 처음부터 한 번 돌려 Finished 줄의 초와 target 크기를 적어 두자. 의존성을 하나 더할 때마다 그 숫자가 어떻게 바뀌는지 보면 크레이트를 고르는 눈이 생긴다.