Skip to content

필사 모드: Rust 생태계 2026 완벽 가이드 - Rust 1.85+ · tokio · axum · actix-web · sqlx · bevy · tauri · leptos · dioxus · embassy · cargo 심층 분석

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며 — 2026년 5월, Rust는 "시스템 언어 표준"으로 굳어졌다

2024년 말 rust-for-linux 패치가 메인라인에 머지되면서 Rust는 "유망한 언어"에서 "리눅스 커널이 채택한 언어"로 신분이 바뀌었다. 2026년 5월 현재, 그 변화는 더 또렷하다. **Cloudflare의 Pingora**(Rust로 작성된 차세대 프록시)는 하루 40조 건이 넘는 요청을 처리하며, **Discord의 Read States 서비스**는 Rust 마이그레이션 이후 99.99% 안정성과 GC 폴 제거를 동시에 달성했고, **Dropbox의 Magic Pocket 스토리지 엔진**, **Figma의 멀티플레이어 HTTP 레이어**, **Mozilla의 Servo**(2024년 Linux Foundation으로 이관)가 Rust 기반으로 굳어졌다.

이 글은 마케팅 매트릭스가 아니라 "2026년 5월 현재 Rust 프로덕션 스택은 어떻게 구성되는가"를 정직하게 짚는다. 1.85 에디션의 변화부터 tokio/axum/sqlx의 실제 코드, Tauri 2의 모바일 GA, Bevy 0.15의 ECS, Embassy의 no_std async, 그리고 한국·일본의 채택 사례까지 비교한다.

Rust 2026 스택 — 8개 레이어로 분해하기

먼저 큰 그림이다. 2026년 표준 Rust 스택은 다음 8개 레이어로 나뉜다.

1. **언어/툴체인**: rustc, cargo, rustup, rust-analyzer

2. **async 런타임**: tokio가 사실상 표준, async-std/smol/embassy가 특수 영역

3. **웹/네트워크**: axum, actix-web 5, poem, rocket 0.5, warp, salvo, loco-rs

4. **데이터/ORM**: sqlx, sea-orm, diesel 2.x, rbatis, sqlite-rs

5. **에러/관측**: anyhow, thiserror, eyre, snafu, miette, tracing

6. **GUI/렌더**: Tauri 2, egui, Iced, Slint, Dioxus, Yew, Leptos, Sycamore

7. **시스템/임베디드/게임**: Embassy, RTIC, embedded-hal, Bevy, winit, gtk-rs

8. **도구 생태계**: cargo-nextest, cargo-mutants, cargo-deny, cargo-audit, cross, binstall

각 레이어를 한두 크레이트가 담당하면 됐던 시대는 끝났다. 지금은 "axum + tokio + sqlx + tracing"이 사실상 백엔드 표준 조합이고, GUI는 "Tauri 2 + Leptos/Dioxus" 또는 "egui/Slint"로 갈라진다. 아래부터 한 레이어씩 본다.

Rust 1.85와 2024 에디션 — async fn in trait, let-else, GAT 안정화

Rust 1.85는 2024 에디션의 첫 번째 안정 릴리스다. 핵심 변화는 다음과 같다.

- **async fn in trait (RPITIT)**: 더 이상 `async-trait` 매크로가 필수가 아니다. dyn-safe 제한은 여전히 있지만, 정적 디스패치 시나리오에서 매크로 없이 작성 가능.

- **GAT(Generic Associated Types)**: 1.65에서 안정화됐지만 2024 에디션에서 다양한 lints가 정리됐다.

- **let-else 패턴**: 1.65부터 사용 가능. 2024 에디션에서 `if let` 임시 수명(temporary lifetime) 규칙이 직관적으로 변경됐다.

- **never type fallback**: `!` 타입의 폴백이 `()`에서 `!`로 바뀌어 더 엄격해졌다. 일부 코드는 명시적 타입 어노테이션 필요.

- **raw lifetime/`r#`**: 식별자 충돌 해소.

대표적인 1.85 스타일 트레이트 정의는 다음과 같다.

use std::error::Error;

// 2024 에디션: async fn in trait, 매크로 불필요

pub trait UserRepo {

async fn find_by_id(&self, id: u64) -> Result<Option<User>, Box<dyn Error + Send + Sync>>;

async fn create(&self, user: NewUser) -> Result<User, Box<dyn Error + Send + Sync>>;

}

pub struct User { pub id: u64, pub email: String }

pub struct NewUser { pub email: String }

pub struct PgUserRepo { pool: sqlx::PgPool }

impl UserRepo for PgUserRepo {

async fn find_by_id(&self, id: u64) -> Result<Option<User>, Box<dyn Error + Send + Sync>> {

let row = sqlx::query_as::<_, (i64, String)>("SELECT id, email FROM users WHERE id = $1")

.bind(id as i64)

.fetch_optional(&self.pool)

.await?;

Ok(row.map(|(id, email)| User { id: id as u64, email }))

}

async fn create(&self, user: NewUser) -> Result<User, Box<dyn Error + Send + Sync>> {

let row: (i64,) = sqlx::query_as("INSERT INTO users(email) VALUES ($1) RETURNING id")

.bind(&user.email)

.fetch_one(&self.pool)

.await?;

Ok(User { id: row.0 as u64, email: user.email })

}

}

tokio 런타임 내부 — 워크 스틸링, LIFO 슬롯, 협력적 스케줄링

tokio는 멀티스레드(M:N) 워크 스틸링 스케줄러를 쓴다. 핵심 메커니즘은 세 가지다.

- **로컬 큐 + 글로벌 큐**: 각 워커는 자신의 로컬 큐(LIFO 슬롯 1개 + FIFO 256개)를 가진다. 가득 차면 절반을 글로벌 큐로 옮긴다.

- **LIFO 슬롯**: 가장 최근에 `wake()`된 태스크를 다음 폴 대상으로 우선 처리해 캐시 지역성을 유지한다.

- **워크 스틸링**: 자기 큐가 비면 무작위 워커의 큐 절반을 훔쳐온다.

tokio 1.40 이후로는 협력적 스케줄링(cooperative scheduling) 예산 기본값이 128로 줄었다. 즉, 한 태스크가 128번 폴(poll) 되면 자동으로 양보(yield) 한다. 무한 루프에서 `tokio::task::yield_now().await`를 명시할 필요가 사실상 사라졌다.

use tokio::sync::mpsc;

use tokio::time::{sleep, Duration};

#[tokio::main(flavor = "multi_thread", worker_threads = 8)]

async fn main() {

let (tx, mut rx) = mpsc::channel::<u64>(1024);

// 프로듀서 100개

for i in 0..100u64 {

let tx = tx.clone();

tokio::spawn(async move {

for j in 0..1000u64 {

let _ = tx.send(i * 1_000 + j).await;

if j % 100 == 0 { sleep(Duration::from_micros(10)).await; }

}

});

}

drop(tx);

// 컨슈머: 단일 태스크

let mut count = 0u64;

while let Some(_v) = rx.recv().await { count += 1; }

println!("received: {count}");

}

`#[tokio::main]`은 단순한 매크로 설탕이고, 실제로는 `tokio::runtime::Builder::new_multi_thread()`를 부른다. 라이브러리에서는 매크로 대신 직접 빌더를 쓰는 게 일반적이다.

async 런타임 비교 — tokio vs async-std vs smol vs embassy

| 런타임 | 타깃 | 스레딩 | I/O 백엔드 | 비고 |

| --- | --- | --- | --- | --- |

| tokio | 서버/네트워크 표준 | multi-thread/current-thread | mio(epoll/kqueue/IOCP) | 2026년 사실상 표준 |

| async-std | 단순 API 지향 | multi-thread | smol-based | 유지보수 모드, 신규 채택 비추 |

| smol | 경량 (1k LOC) | single/multi | polling/async-io | 임베디드, 학습 목적 |

| embassy | no_std/펌웨어 | cooperative, no-alloc 가능 | HAL 통합 | RP2040/STM32/ESP32 |

| glommio | Linux-only io_uring | thread-per-core | io_uring | 데이터베이스/스토리지 |

2026년 5월 기준 "라이브러리는 런타임 무관(runtime-agnostic)으로, 애플리케이션은 tokio로"가 표준 패턴이다. `tokio::main`을 라이브러리 크레이트에 박지 않는 게 매너다.

axum — async 웹 프레임워크의 사실상 표준

tokio 팀이 직접 만드는 axum은 0.7~0.8을 거치며 사실상 표준이 됐다. 특징은 `tower::Service` 기반 미들웨어, 강력한 추출기(extractor) 시스템, hyper 위에 얇게 얹은 디자인이다.

use axum::{

Router,

extract::{Path, State},

response::Json,

routing::{get, post},

http::StatusCode,

};

use serde::{Deserialize, Serialize};

use std::sync::Arc;

use sqlx::PgPool;

#[derive(Clone)]

struct AppState { pool: PgPool }

#[derive(Serialize)]

struct User { id: i64, email: String }

#[derive(Deserialize)]

struct CreateUser { email: String }

async fn get_user(

State(state): State<Arc<AppState>>,

Path(id): Path<i64>,

) -> Result<Json<User>, StatusCode> {

let row = sqlx::query_as::<_, (i64, String)>(

"SELECT id, email FROM users WHERE id = $1"

)

.bind(id)

.fetch_optional(&state.pool)

.await

.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?

.ok_or(StatusCode::NOT_FOUND)?;

Ok(Json(User { id: row.0, email: row.1 }))

}

async fn create_user(

State(state): State<Arc<AppState>>,

Json(payload): Json<CreateUser>,

) -> Result<(StatusCode, Json<User>), StatusCode> {

let row: (i64,) = sqlx::query_as("INSERT INTO users(email) VALUES ($1) RETURNING id")

.bind(&payload.email)

.fetch_one(&state.pool)

.await

.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

Ok((StatusCode::CREATED, Json(User { id: row.0, email: payload.email })))

}

#[tokio::main]

async fn main() {

let pool = PgPool::connect(&std::env::var("DATABASE_URL").unwrap()).await.unwrap();

let state = Arc::new(AppState { pool });

let app = Router::new()

.route("/users/:id", get(get_user))

.route("/users", post(create_user))

.with_state(state);

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();

axum::serve(listener, app).await.unwrap();

}

`Path`, `State`, `Json`, `Query` 같은 추출기는 모두 `FromRequestParts` 또는 `FromRequest` 트레이트로 확장 가능하다. 미들웨어는 `tower::Layer`로 합성해 `Router::layer()`에 꽂는다.

actix-web 5와 다른 웹 프레임워크들 — poem · rocket · warp · salvo · loco-rs

axum이 표준이라고 해도 다른 프레임워크도 살아 있다.

- **actix-web 5**: 액터 모델은 점점 옅어지고 일반 async-fn 핸들러 중심으로 자리 잡았다. TechEmpower 벤치마크에서 여전히 최상위권. 마이크로벤치 성능을 짜내는 팀이 선호.

- **poem**: tokio 위에 axum과 유사한 추출기 디자인. OpenAPI 자동 생성(poem-openapi)에 강점.

- **rocket 0.5**: 1.0 트랙으로 안정화됐지만 async 적응이 느려 신규 채택은 감소.

- **warp**: 필터 콤비네이터 디자인. 유지보수 활동은 줄었다.

- **salvo**: 중국 커뮤니티에서 활발. 트리 기반 라우팅.

- **loco-rs**: "Rust의 Rails"를 표방. 풀스택 어셈블리(axum + sea-orm + 백그라운드 작업 + 메일러).

| 프레임워크 | 핵심 특징 | 추천 시나리오 |

| --- | --- | --- |

| axum | tower 생태계, 추출기 | 일반 백엔드 표준 |

| actix-web 5 | 성능 최상위 | 초고성능 게이트웨이 |

| poem | OpenAPI 1급 시민 | 스키마 중심 API |

| loco-rs | 풀스택 컨벤션 | "Rails of Rust" 빠른 스타트 |

| salvo | 트리 라우팅 | 중국 시장/대형 라우팅 트리 |

sqlx · sea-orm · diesel 2.x — 데이터베이스 레이어 비교

DB 레이어는 세 갈래로 정리됐다.

- **sqlx 0.8+**: async, 컴파일타임 쿼리 검사(`query!` 매크로), Postgres/MySQL/SQLite/MSSQL. 마이그레이션은 `sqlx-cli`. 2026년 표준.

- **sea-orm**: 풀 ORM, ActiveRecord 패턴, 마이그레이션 DSL, 엔티티 코드 생성(`sea-orm-cli`). loco-rs의 기본 ORM.

- **diesel 2.x**: 동기 ORM. `diesel-async`로 async 어댑터 지원. 컴파일타임 안전성 최강, 다만 매크로 학습곡선이 가파르다.

- **rbatis**: 중국 커뮤니티 발 async ORM. Mybatis-스타일 XML/매크로.

sqlx의 컴파일타임 쿼리 검사 예시.

use sqlx::PgPool;

#[derive(sqlx::FromRow)]

struct Order { id: i64, user_id: i64, total_cents: i64, status: String }

async fn list_user_orders(pool: &PgPool, user_id: i64) -> sqlx::Result<Vec<Order>> {

// 매크로가 컴파일타임에 DB에 접속해 SELECT 컬럼 타입을 검사한다

let orders = sqlx::query_as!(

Order,

r#"SELECT id, user_id, total_cents, status

FROM orders

WHERE user_id = $1

ORDER BY id DESC

LIMIT 100"#,

user_id

)

.fetch_all(pool)

.await?;

Ok(orders)

}

`sqlx::query_as!`는 `DATABASE_URL` 환경 변수 또는 `sqlx-data.json`(오프라인 모드)으로 DB 스키마를 미리 확인한다. CI에서 오프라인 모드를 쓰는 게 표준이다.

| 라이브러리 | 스타일 | 안전성 | async | 추천 |

| --- | --- | --- | --- | --- |

| sqlx | SQL 우선 + 매크로 검사 | 컴파일타임 검증 | 네이티브 | 백엔드 표준 |

| sea-orm | ActiveRecord ORM | 런타임 | 네이티브 | 풀스택/loco-rs |

| diesel | 타입드 DSL | 컴파일타임 최강 | adapter 필요 | 안전성 우선 |

| rbatis | XML/매크로 SQL | 런타임 | 네이티브 | 중국 시장 호환 |

에러 처리 — anyhow · thiserror · eyre · snafu · miette

에러 처리 크레이트는 두 축으로 갈린다.

- **라이브러리용 에러 타입 정의**: `thiserror`(파생 매크로), `snafu`(컨텍스트 추가 강조).

- **애플리케이션용 에러 합치기**: `anyhow`(`anyhow::Error`로 모두 흡수), `eyre`(anyhow + 리포터 커스터마이즈), `miette`(예쁜 진단 출력).

전형적인 라이브러리 + 애플리케이션 분리.

// 라이브러리 측: thiserror로 명시적 에러 타입

use thiserror::Error;

#[derive(Debug, Error)]

pub enum BillingError {

#[error("invoice not found: {0}")]

NotFound(i64),

#[error("database error")]

Db(#[from] sqlx::Error),

#[error("payment provider error: {0}")]

Provider(String),

}

pub async fn charge(invoice_id: i64) -> Result<(), BillingError> {

Err(BillingError::Provider("stripe timeout".into()))

}

// 애플리케이션 측: anyhow로 컨텍스트 누적

use anyhow::Context;

pub async fn process_batch(ids: &[i64]) -> anyhow::Result<()> {

for &id in ids {

charge(id).await

.with_context(|| format!("failed to charge invoice {id}"))?;

}

Ok(())

}

`miette`는 컴파일러 진단처럼 소스 위치를 가리키는 출력을 만든다. CLI 사용자 친화적 도구를 만들 때 자주 쓴다.

tracing + tracing-subscriber — 비동기 관측의 표준

`println!`/`log`/`env_logger`를 지나, 2026년 Rust의 관측 표준은 `tracing`이다. tokio 팀이 만들었고 비동기 코드에 자연스럽다.

use tracing::{info, instrument, error};

use tracing_subscriber::{EnvFilter, fmt, prelude::*};

#[instrument(skip(pool))]

async fn handle_request(pool: &sqlx::PgPool, user_id: i64) -> anyhow::Result<()> {

info!(user_id, "processing request");

let _row = sqlx::query("SELECT 1").fetch_one(pool).await?;

Ok(())

}

#[tokio::main]

async fn main() {

tracing_subscriber::registry()

.with(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))

.with(fmt::layer().json())

.init();

info!("server starting");

}

`tracing-opentelemetry` 어댑터를 추가하면 OTEL 트레이서로 그대로 흘려보낼 수 있고, `tracing-loki`/`tracing-bunyan-formatter` 같은 익스포터도 풍부하다.

serde 2026 — 표준의 자리, miniserde · postcard

`serde`는 사실상 표준 직렬화 프레임워크다. 2026년 5월 기준 1.0 라인업이 계속 유지되고 있고, "serde 2.0"의 RFC가 논의 중이지만 아직 안정 릴리스는 없다.

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]

struct ApiResponse {

#[serde(rename = "userId")]

user_id: i64,

#[serde(default)]

tags: Vec<String>,

#[serde(skip_serializing_if = "Option::is_none")]

email: Option<String>,

}

fn parse_response(s: &str) -> serde_json::Result<ApiResponse> {

serde_json::from_str(s)

}

대안군:

- **miniserde**: 매크로 컴파일 시간을 줄인 미니멀 직렬화 라이브러리. 단순 JSON 전용.

- **postcard**: `serde`-기반 임베디드 친화적 바이너리 포맷. `no_std` 호환.

- **bincode 2.0**: 표준 빠른 바이너리. derive 매크로 분리.

- **rkyv**: zero-copy 역직렬화. 성능 극단 추구.

Tauri 2 — 데스크톱과 모바일을 같은 코드로

Tauri 1이 "Electron의 가벼운 대안"이었다면, Tauri 2(2024년 GA, 2026년 5월 안정 트랙)는 데스크톱 + 안드로이드 + iOS를 같은 Rust 코어로 묶는다.

// src-tauri/src/lib.rs

use tauri::command;

#[command]

async fn greet(name: String) -> Result<String, String> {

Ok(format!("Hello, {name}!"))

}

#[command]

async fn read_file(path: String) -> Result<String, String> {

tokio::fs::read_to_string(&path).await.map_err(|e| e.to_string())

}

#[cfg_attr(mobile, tauri::mobile_entry_point)]

pub fn run() {

tauri::Builder::default()

.plugin(tauri_plugin_shell::init())

.invoke_handler(tauri::generate_handler![greet, read_file])

.run(tauri::generate_context!())

.expect("error while running tauri application");

}

플러그인 시스템이 정비돼 `tauri-plugin-sql`, `tauri-plugin-store`, `tauri-plugin-deep-link`, `tauri-plugin-notification` 같은 1급 플러그인이 모바일까지 커버한다. 프론트는 Vanilla/React/Vue/Svelte/Leptos/Dioxus 모두 가능.

Leptos · Dioxus · Yew · Sycamore — Rust 풀스택 프론트엔드

WASM + Rust 풀스택 프레임워크는 네 갈래다.

- **Leptos 0.7+**: 시그널 기반 fine-grained 반응성, SSR/CSR/하이드레이션/`server fn` 일급 지원. `cargo-leptos`로 풀스택 빌드.

- **Dioxus 0.6+**: RSX(React 유사) 매크로, 데스크톱/모바일/웹/터미널 멀티 타깃. 2025년 D팀이 풀타임 OSS 회사로 자리 잡았다.

- **Yew**: VDOM 기반 클래식. 진입은 친숙하지만 풀스택 도구는 Leptos에 밀린다.

- **Sycamore**: Solid 영감 시그널 기반. 학습 목적/소규모 SPA에 적합.

Leptos의 풀스택 컴포넌트 예시.

use leptos::*;

use leptos::server_fn::ServerFn;

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone)]

pub struct Todo { pub id: i64, pub title: String, pub done: bool }

#[server]

pub async fn list_todos() -> Result<Vec<Todo>, ServerFnError> {

Ok(vec![Todo { id: 1, title: "ship".into(), done: false }])

}

#[component]

pub fn TodoList() -> impl IntoView {

let todos = create_resource(|| (), |_| async move { list_todos().await });

view! {

{move || todos.get().map(|res| match res {

Ok(items) => view! {

}.into_view(),

Err(_) => view! { <p>"error"</p> }.into_view(),

})}

}

}

Dioxus의 같은 화면.

use dioxus::prelude::*;

#[derive(Clone, PartialEq, Props)]

struct Todo { id: i64, title: String, done: bool }

fn TodoList(cx: Scope) -> Element {

let todos = use_state(cx, || vec![Todo { id: 1, title: "ship".into(), done: false }]);

cx.render(rsx! {

ul {

todos.iter().map(|t| rsx!{

li { key: "{t.id}", "{t.title}" }

})

}

})

}

| 프레임워크 | 패러다임 | 멀티타깃 | 풀스택 | 추천 |

| --- | --- | --- | --- | --- |

| Leptos | 시그널, SSR 1급 | 웹 | 강함 | 풀스택 웹 표준 |

| Dioxus | RSX, 멀티 렌더러 | 웹/데스크톱/모바일/TUI | 진행 중 | 멀티 타깃 |

| Yew | VDOM | 웹 | 약함 | 학습/단순 SPA |

| Sycamore | 시그널 | 웹 | 약함 | 학습 |

egui · Iced · Slint — 네이티브 GUI 라이브러리

Tauri가 "웹뷰 기반"이라면, 네이티브 GUI는 세 갈래다.

- **egui**: 즉시 모드(immediate mode) GUI. 자체 렌더러(`eframe`), 짧은 코드, 게임/내부 도구에 적합.

- **Iced**: Elm 영감, Cmd/Sub 패턴. 데스크톱 앱.

- **Slint**: DSL(`.slint` 파일) 기반. 임베디드 친화, 상용 라이선스도 제공.

use eframe::egui;

struct App { name: String, age: u32 }

impl eframe::App for App {

fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {

egui::CentralPanel::default().show(ctx, |ui| {

ui.heading("My egui Application");

ui.horizontal(|ui| {

ui.label("Your name: ");

ui.text_edit_singleline(&mut self.name);

});

ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));

if ui.button("Increment").clicked() { self.age += 1; }

ui.label(format!("Hello '{}', age {}", self.name, self.age));

});

}

}

fn main() -> eframe::Result<()> {

let opts = eframe::NativeOptions::default();

eframe::run_native(

"demo",

opts,

Box::new(|_| Ok(Box::new(App { name: "Arthur".into(), age: 42 }))),

)

}

| 라이브러리 | 패러다임 | 렌더 | 적합 시나리오 |

| --- | --- | --- | --- |

| egui | immediate mode | wgpu/glow | 게임 내 디버그, 내부 도구 |

| Iced | Elm-like retained | wgpu/tiny-skia | 데스크톱 앱 |

| Slint | DSL retained | software/skia/femtovg | 임베디드, 키오스크 |

| Dioxus desktop | 웹뷰 | OS WebView | 웹 자산 재사용 |

| Tauri 2 | 웹뷰 | OS WebView | 풀 데스크톱 + 모바일 |

Bevy 0.15+ — Rust 게임 엔진의 사실상 표준

Bevy는 ECS 기반 데이터 지향 게임 엔진이다. 2025년 0.15에서 BSN(Bevy Scene Notation)·렌더 그래프 v2·UI 개편이 들어갔고, 2026년 0.16/0.17 라인에서 에디터·핫리로드·머티리얼 추가가 진행 중이다.

use bevy::prelude::*;

#[derive(Component)]

struct Player { speed: f32 }

fn spawn_player(mut commands: Commands) {

commands.spawn((

Player { speed: 250.0 },

Sprite::from_color(Color::srgb(0.2, 0.7, 1.0), Vec2::new(40.0, 40.0)),

Transform::default(),

));

}

fn move_player(

time: Res<Time>,

keys: Res<ButtonInput<KeyCode>>,

mut q: Query<(&Player, &mut Transform)>,

) {

for (p, mut t) in &mut q {

let mut dir = Vec3::ZERO;

if keys.pressed(KeyCode::KeyW) { dir.y += 1.0; }

if keys.pressed(KeyCode::KeyS) { dir.y -= 1.0; }

if keys.pressed(KeyCode::KeyA) { dir.x -= 1.0; }

if keys.pressed(KeyCode::KeyD) { dir.x += 1.0; }

t.translation += dir.normalize_or_zero() * p.speed * time.delta_secs();

}

}

fn main() {

App::new()

.add_plugins(DefaultPlugins)

.add_systems(Startup, spawn_player)

.add_systems(Update, move_player)

.run();

}

Bevy의 매력은 "ECS가 일급 시민이고, 시스템이 그냥 함수"라는 점이다. 게임뿐 아니라 시뮬레이션·툴 백엔드로도 채택이 늘고 있다.

Embassy · RTIC · embedded-hal — 임베디드/펌웨어 Rust

`no_std` 임베디드 영역에서 2026년의 흐름은 명확하다. **Embassy가 사실상 표준**이고, 인터럽트 우선순위 기반의 결정론이 필요한 곳은 **RTIC**가 자리를 지킨다.

#![no_std]

#![no_main]

use embassy_executor::Spawner;

use embassy_rp::gpio::{Level, Output};

use embassy_time::{Duration, Timer};

use {defmt_rtt as _, panic_probe as _};

#[embassy_executor::task]

async fn blink(mut led: Output<'static>) {

loop {

led.set_high();

Timer::after(Duration::from_millis(500)).await;

led.set_low();

Timer::after(Duration::from_millis(500)).await;

}

}

#[embassy_executor::main]

async fn main(spawner: Spawner) {

let p = embassy_rp::init(Default::default());

let led = Output::new(p.PIN_25, Level::Low);

spawner.spawn(blink(led)).unwrap();

}

`embedded-hal 1.0`이 2023년 말 안정화되면서 드라이버 생태계가 일원화됐다. STM32/RP2040/nRF52/ESP32 가릴 것 없이 `embedded-hal` 트레이트를 구현한 HAL 위에서 같은 드라이버가 돈다.

CLI · 시스템 도구 — clap 4.5 · argh · ripgrep · bat · fd

CLI 파서는 사실상 `clap`이 표준이다.

use clap::{Parser, Subcommand};

#[derive(Parser)]

#[command(name = "blogctl", version, about = "Blog management CLI")]

struct Cli {

#[command(subcommand)]

command: Cmd,

}

#[derive(Subcommand)]

enum Cmd {

/// Create a new post

New { title: String, #[arg(short, long)] draft: bool },

/// Publish a post

Publish { slug: String },

}

fn main() {

let cli = Cli::parse();

match cli.command {

Cmd::New { title, draft } => println!("new post: {title} (draft={draft})"),

Cmd::Publish { slug } => println!("publish {slug}"),

}

}

`argh`(Google)는 derive 매크로 컴파일 시간이 짧아 작은 도구에 적합. 시스템 명령 라인 도구 중 Rust 작성이 사실상 표준이 된 사례는 `ripgrep`, `fd`, `bat`, `eza`, `zoxide`, `bottom`, `dust`, `procs`, `hyperfine`, `tokei`, `mdbook`이다.

Cargo 워크스페이스 · build.rs · cross-compile

대형 Rust 프로젝트는 워크스페이스로 묶어 크레이트들을 함께 관리한다.

워크스페이스 루트의 Cargo.toml

[workspace]

resolver = "3"

members = ["crates/api", "crates/domain", "crates/storage"]

[workspace.dependencies]

tokio = { version = "1.40", features = ["full"] }

sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres"] }

axum = "0.8"

serde = { version = "1", features = ["derive"] }

serde_json = "1"

thiserror = "1"

anyhow = "1"

[profile.release]

opt-level = 3

lto = "thin"

codegen-units = 1

strip = "symbols"

크로스 컴파일은 `cross` 크레이트가 표준이다. `cross build --target aarch64-unknown-linux-musl --release` 한 줄이면 Docker 기반 툴체인이 정적 바이너리를 만들어 준다.

Cargo 도구 생태 — nextest · mutants · deny · audit · machete · expand · binstall

표준 `cargo test`만으로는 부족하다. 2026년 표준 보조 도구는 다음과 같다.

| 도구 | 용도 |

| --- | --- |

| cargo-nextest | 병렬 테스트 러너, 멋진 출력, 격리 |

| cargo-mutants | 변이 테스트, 테스트 품질 검증 |

| cargo-deny | 라이선스/취약점/중복 의존 검사 |

| cargo-audit | RUSTSEC DB 기반 취약점 스캔 |

| cargo-machete | 사용되지 않는 의존성 탐지 |

| cargo-expand | 매크로 펼친 결과 확인 |

| cargo-binstall | 사전 빌드 바이너리 설치 |

| cargo-watch | 파일 변경 감지 자동 재빌드 |

| cargo-leptos | Leptos 풀스택 빌드 |

표준 CI 한 묶음

cargo fmt --all -- --check

cargo clippy --all-targets --all-features -- -D warnings

cargo nextest run --workspace --all-features

cargo deny check

cargo audit

cargo machete

WebAssembly — wasm-bindgen · wasm-pack · wasmtime · wasmer

Rust + WASM은 두 진영이다.

- **브라우저용**: `wasm-bindgen` + `wasm-pack`. JS와 Rust 간 자동 바인딩.

- **서버/엣지용**: `wasmtime`(Bytecode Alliance, Fastly·Microsoft 후원), `wasmer`. WASI Preview 2가 2024년 정착하면서 컴포넌트 모델 기반 모듈화가 진행 중.

Cloudflare Workers는 Rust+WASM을 1급 시민으로 지원하고, Fermyon·Spin·WasmCloud 같은 회사가 WASM 기반 서버리스를 끌어가고 있다.

rust-for-linux · Cloudflare Pingora · Discord · Dropbox · Figma — 프로덕션 사례

Rust 채택은 더 이상 "스타트업의 실험"이 아니다.

| 회사/프로젝트 | 채택 시점 | Rust 사용처 | 임팩트 |

| --- | --- | --- | --- |

| Linux Kernel | 2022 머지, 2024 mainline 확장 | 드라이버, Android Binder | 시스템 언어 인증 |

| Cloudflare Pingora | 2022 발표, 2024 OSS | 차세대 HTTP 프록시 (NGINX 대체) | 일 40T 요청 처리 |

| Discord | 2020~ | Read States, 게이트웨이 | GC pause 제거, 99.99% 안정성 |

| Dropbox | 2014~ | Magic Pocket 스토리지 | 엑사바이트급 |

| Figma | 2022~ | 멀티플레이어 HTTP 레이어 | 동시 편집 성능 |

| Mozilla / Servo | 2024 LF 이관 | 차세대 브라우저 엔진 | 임베디드 브라우저 |

| AWS | 전사 | Firecracker, Bottlerocket, S3 일부 | 컨테이너/마이크로VM |

| Google | 안드로이드 | Binder, Crash Subsystem | 시스템 메모리 안전 |

| Microsoft | Windows | 일부 시스템 컴포넌트 | 메모리 안전 강화 |

| Meta | 백엔드 | 서비스 메시 일부 | Rust 공식 채택 |

함정 · 트레이드오프 — Rust를 도입할 때 빠지기 쉬운 함정

Rust를 새 프로젝트에 도입할 때 자주 보는 함정 다섯 가지.

1. **컴파일 시간**: 큰 워크스페이스에서 풀 빌드는 길다. `cargo check` 위주 워크플로, `sccache`, `mold` 링커, debug-info=line-tables-only 같은 셋업이 표준이다.

2. **async + Send 경계**: `Box<dyn Trait>`을 도처에 쓰지 말 것. 라이브러리 트레이트는 가급적 `Send + 'static` 경계를 명시.

3. **dyn 호환성과 RPITIT**: 모든 async-trait를 RPITIT로 옮기면 dyn-trait가 깨진다. dyn 사용 트레이트는 여전히 `async-trait` 매크로가 필요할 수 있다.

4. **에러 타입 폭주**: 라이브러리 한 곳에 거대한 `enum Error` 박지 말 것. 모듈마다 작은 에러 타입을 두고 `From`으로 끌어올린다.

5. **unsafe 남용**: 99% 의 코드는 unsafe가 필요 없다. FFI/임베디드/SIMD가 아니면 멈춰서 다시 본다.

한국 · 일본의 Rust 채택 — Naver · Kakao · CyberAgent · Mercari · Sansan

한국·일본도 적극적이다.

- **네이버**: 검색/광고 일부 백엔드, 미디어 처리 파이프라인에 Rust 도입. 사내 Rust 스터디·세미나가 정기 운영된다.

- **카카오 브레인 / 카카오엔터프라이즈**: ML 추론 서버, 모델 게이트웨이에 Rust 활용. PyO3로 파이썬과 결합.

- **Discord Korea / 트위치 코리아 그룹**: 글로벌 Rust 스택을 그대로 활용.

- **CyberAgent**: 광고·게임 인프라 일부를 Rust로 재작성. AbemaTV의 일부 마이크로서비스.

- **Mercari**: 검색·인프라 도구·CLI 일부를 Rust로 작성. Rust 채용 공고 상시.

- **Sansan**: 명함 인식·OCR 후처리 파이프라인에 Rust 채택.

- **LINE Yahoo**: 일부 시스템 데몬, 빌드 도구를 Rust로 마이그레이션.

도쿄와 서울 모두 Rust 밋업이 분기마다 열린다. 한국은 "Rust Korea" 슬랙·디스코드·페이스북 그룹이, 일본은 "Rust.Tokyo" 컨퍼런스가 정기 행사로 자리 잡았다.

Rust 배우는 순서 — 2026년 추천 로드맵

처음 Rust를 만지는 개발자에게 추천하는 흐름이다.

1. **The Rust Programming Language**("the book") 1~10장: 소유권·빌림·라이프타임의 직관을 잡는다.

2. **rustlings**: 작은 빈칸 채우기로 컴파일러 메시지에 익숙해진다.

3. **`cargo new`로 CLI 만들기**: clap + serde + anyhow 조합.

4. **tokio + axum으로 작은 API**: sqlx + Postgres + tracing까지.

5. **2024 에디션 변경점 + async fn in trait** 학습.

6. 도메인 선택:

- 웹/풀스택: Leptos 또는 Dioxus.

- 데스크톱: Tauri 2 또는 egui.

- 게임: Bevy.

- 임베디드: Embassy + RP2040 또는 STM32 Discovery.

- 시스템: rust-for-linux, Firecracker, Pingora 소스 읽기.

"빨리 잘 짜기"보다 "컴파일러와 대화하면서 모델을 잡기"가 핵심이다. 컴파일러 에러는 친구다.

마무리 — 2026년의 Rust는 "선택의 언어"가 아닌 "기본의 언어"

2024년 rust-for-linux 머지, 2024년 Tauri 2 GA, 2025년 Pingora 오픈소스화, 2025년 axum 0.8, 2026년 Rust 1.85(2024 에디션)까지 흐름이 모이면, 2026년 5월 Rust는 더 이상 "쓰면 좋은 언어"가 아니다. 백엔드는 tokio + axum + sqlx, 데스크톱·모바일은 Tauri 2, 게임은 Bevy, 임베디드는 Embassy, 풀스택 웹은 Leptos/Dioxus가 표준이 됐다.

핵심은 더 이상 "Rust를 써야 하는가?"가 아니라 "어디에 Rust를 쓰는가?"다. 그리고 그 답은 점점 더 많은 영역으로 확장되고 있다.

References

- Rust 공식 — https://www.rust-lang.org/

- The Rust Book — https://doc.rust-lang.org/book/

- Rust 블로그 — https://blog.rust-lang.org/

- tokio — https://tokio.rs/

- axum — https://github.com/tokio-rs/axum

- actix-web — https://actix.rs/

- sqlx — https://github.com/launchbadge/sqlx

- Diesel — https://diesel.rs/

- SeaORM — https://www.sea-ql.org/SeaORM/

- Bevy — https://bevyengine.org/

- Tauri — https://tauri.app/

- Leptos — https://leptos.dev/

- Dioxus — https://dioxuslabs.com/

- Yew — https://yew.rs/

- Embassy — https://embassy.dev/

- crates.io — https://crates.io/

- rust-for-linux — https://rust-for-linux.com/

- Cloudflare Pingora — https://github.com/cloudflare/pingora

- Servo (Linux Foundation) — https://servo.org/

- Discord Rust 사례 — https://discord.com/blog/why-discord-is-switching-from-go-to-rust

현재 단락 (1/494)

2024년 말 rust-for-linux 패치가 메인라인에 머지되면서 Rust는 "유망한 언어"에서 "리눅스 커널이 채택한 언어"로 신분이 바뀌었다. 2026년 5월 현재, 그 변...

작성 글자: 0원문 글자: 19,258작성 단락: 0/494