Skip to content

필사 모드: Rust Ecosystem 2026 Deep-Dive — Rust 1.85+, tokio, axum, actix-web, sqlx, Bevy, Tauri, Leptos, Dioxus, Embassy, Cargo

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

Intro — In May 2026 Rust has hardened into "the systems language standard"

When the rust-for-linux patches were merged into the mainline kernel in late 2024, Rust crossed a line from "promising" to "the language Linux adopted." In May 2026 the shift is even sharper. **Cloudflare's Pingora** (the Rust proxy replacing NGINX inside Cloudflare) handles more than 40 trillion requests per day; **Discord's Read States service** killed GC pauses and hit 99.99% reliability after the Rust rewrite; **Dropbox's Magic Pocket** storage engine, **Figma's multiplayer HTTP layer**, and **Mozilla's Servo** (transferred to the Linux Foundation in 2024) all run on Rust.

This article is not a marketing matrix. It honestly walks through "what does a 2026 production Rust stack actually look like" — from 1.85 / 2024 edition changes, tokio's scheduler, axum/sqlx code, Tauri 2 mobile GA, Bevy 0.15 ECS, Embassy `no_std` async, all the way to Korea/Japan adoption.

The 2026 Rust stack — broken into 8 layers

First, the big picture. The standard 2026 Rust stack divides into 8 layers.

1. **Language / toolchain**: rustc, cargo, rustup, rust-analyzer

2. **Async runtime**: tokio is the de-facto standard; async-std / smol / embassy fill niches

3. **Web / networking**: axum, actix-web 5, poem, rocket 0.5, warp, salvo, loco-rs

4. **Data / ORM**: sqlx, sea-orm, diesel 2.x, rbatis

5. **Errors / observability**: anyhow, thiserror, eyre, snafu, miette, tracing

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

7. **Systems / embedded / games**: Embassy, RTIC, embedded-hal, Bevy, winit, gtk-rs

8. **Tooling ecosystem**: cargo-nextest, cargo-mutants, cargo-deny, cargo-audit, cross, binstall

The era when a single crate owned each layer is over. "axum + tokio + sqlx + tracing" is now the de-facto backend combo, while GUI splits into "Tauri 2 + Leptos/Dioxus" or "egui/Slint." We walk through every layer below.

Rust 1.85 and the 2024 edition — async fn in trait, let-else, stabilized GATs

Rust 1.85 is the first stable release of the 2024 edition. Key changes:

- **async fn in trait (RPITIT)**: the `async-trait` macro is no longer mandatory. The dyn-safety restriction remains, but for static dispatch you can skip the macro.

- **GAT (Generic Associated Types)**: stabilized in 1.65, with many lints cleaned up in the 2024 edition.

- **let-else**: available since 1.65. The 2024 edition makes temporary lifetimes for `if let` more intuitive.

- **never type fallback**: `!` now falls back to `!` rather than `()`. Some code needs explicit type annotations.

- **raw lifetimes / `r#`**: resolves identifier collisions.

A representative 1.85-style trait definition looks like this.

use std::error::Error;

// 2024 edition: async fn in trait, no macro required

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 runtime internals — work stealing, LIFO slot, cooperative scheduling

tokio uses an M:N work-stealing scheduler. There are three core mechanisms.

- **Local queue + global queue**: each worker owns a local queue (1 LIFO slot + 256 FIFO slots). When it overflows, half of it spills into the global queue.

- **LIFO slot**: the most recently `wake()`d task is polled first, preserving cache locality.

- **Work stealing**: when a worker's queue is empty, it steals half of another worker's queue at random.

Since tokio 1.40 the cooperative scheduling budget defaults to 128. A task that polls 128 times yields automatically — explicit `tokio::task::yield_now().await` in tight loops is almost never needed anymore.

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 producers

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);

// single consumer task

let mut count = 0u64;

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

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

}

`#[tokio::main]` is just sugar; under the hood it calls `tokio::runtime::Builder::new_multi_thread()`. In libraries you typically use the builder directly instead of the macro.

Async runtimes compared — tokio vs async-std vs smol vs embassy

| Runtime | Target | Threading | I/O backend | Note |

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

| tokio | Server / networking standard | multi-thread / current-thread | mio (epoll/kqueue/IOCP) | De-facto standard in 2026 |

| async-std | Simple API-first | multi-thread | smol-based | Maintenance mode; not recommended for new projects |

| smol | Lightweight (~1k LOC) | single / multi | polling / async-io | Embedded, educational |

| embassy | no_std / firmware | cooperative, optionally no-alloc | HAL integration | RP2040 / STM32 / ESP32 |

| glommio | Linux-only io_uring | thread-per-core | io_uring | Databases / storage |

As of May 2026 the standard pattern is "libraries stay runtime-agnostic; applications pick tokio." It is bad manners to bake `#[tokio::main]` into a library crate.

axum — the de-facto async web framework

Built by the tokio team itself, axum went through 0.7 and 0.8 and is now the standard. The defining traits are `tower::Service`-based middleware, a powerful extractor system, and a thin layer over 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();

}

Extractors like `Path`, `State`, `Json`, `Query` are all extensible via the `FromRequestParts` or `FromRequest` traits. Middleware composes through `tower::Layer` and plugs in via `Router::layer()`.

actix-web 5 and the other web frameworks — poem, rocket, warp, salvo, loco-rs

Even with axum as the standard, the alternatives are alive and worth knowing.

- **actix-web 5**: the actor model has faded; idiomatic actix-web is now ordinary async-fn handlers. Still at the top of TechEmpower benchmarks. Preferred by teams that micro-tune for throughput.

- **poem**: an extractor design similar to axum, on top of tokio. Standout strength is auto-OpenAPI generation via `poem-openapi`.

- **rocket 0.5**: stabilized on the 1.0 track, but async adoption was slow and new uptake is dropping.

- **warp**: filter combinator design. Maintenance activity is reduced.

- **salvo**: active in the Chinese community. Tree-based router.

- **loco-rs**: "the Rails of Rust." Bundles axum + sea-orm + background jobs + mailer into a full-stack assembly.

| Framework | Defining trait | Recommended scenario |

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

| axum | tower ecosystem, extractors | Default backend choice |

| actix-web 5 | Top-tier throughput | Ultra-high-performance gateways |

| poem | OpenAPI as a first-class citizen | Schema-first APIs |

| loco-rs | Full-stack conventions | "Rails of Rust" fast starts |

| salvo | Tree-based router | China market / very large routing trees |

sqlx, sea-orm, diesel 2.x — comparing the database layer

The DB layer settled into three camps.

- **sqlx 0.8+**: async, compile-time query checking (`query!` macro), Postgres / MySQL / SQLite / MSSQL. Migrations via `sqlx-cli`. The 2026 default.

- **sea-orm**: full ORM, ActiveRecord-style, migration DSL, entity code generation via `sea-orm-cli`. The default ORM for loco-rs.

- **diesel 2.x**: synchronous ORM with `diesel-async` adapter. Strongest compile-time safety, but the macro learning curve is steep.

- **rbatis**: async ORM born in China. Mybatis-style XML / macros.

A sqlx compile-time-checked query example.

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>> {

// The macro hits the DB at compile time to check SELECT column types.

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!` looks up the schema either through `DATABASE_URL` or via `sqlx-data.json` (offline mode). Using offline mode in CI is standard practice.

| Crate | Style | Safety | async | Use when |

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

| sqlx | SQL-first + macro checks | Compile-time | Native | Backend default |

| sea-orm | ActiveRecord ORM | Runtime | Native | Full-stack / loco-rs |

| diesel | Typed DSL | Strongest compile-time | Adapter needed | Safety above all |

| rbatis | XML / macro SQL | Runtime | Native | China-market compatibility |

Error handling — anyhow, thiserror, eyre, snafu, miette

The error-handling crates split along two axes.

- **Library error types**: `thiserror` (derive macros), `snafu` (context-adding focus).

- **Application error aggregation**: `anyhow` (absorbs anything into `anyhow::Error`), `eyre` (anyhow + custom reporter), `miette` (pretty diagnostic output).

A typical library/application separation.

// Library side: explicit error types via 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()))

}

// Application side: accumulate context with 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` produces compiler-style diagnostics that point at source locations. It is heavily used in user-facing CLI tools.

tracing + tracing-subscriber — the observability standard for async Rust

Past `println!` / `log` / `env_logger`, the 2026 standard for Rust observability is `tracing`. Built by the tokio team, it slots naturally into async code.

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");

}

Adding `tracing-opentelemetry` forwards spans straight into an OTEL tracer; ecosystem exporters like `tracing-loki` and `tracing-bunyan-formatter` are abundant.

serde in 2026 — still the standard, plus miniserde and postcard

`serde` is effectively the standard serialization framework. As of May 2026 the 1.0 line is still maintained; an RFC for "serde 2.0" is under discussion but no stable release yet.

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)

}

Alternatives:

- **miniserde**: minimalist serializer that drastically cuts macro compile time. JSON only.

- **postcard**: `serde`-based binary format designed for embedded targets. `no_std` compatible.

- **bincode 2.0**: standard fast binary format. Derive macros are split out.

- **rkyv**: zero-copy deserialization. Performance-first choice.

Tauri 2 — desktop and mobile from the same code

If Tauri 1 was "a lighter Electron alternative," Tauri 2 (GA in 2024, on a stable track by May 2026) bundles desktop + Android + iOS around the same Rust core.

// 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");

}

The plugin system has matured; first-party plugins such as `tauri-plugin-sql`, `tauri-plugin-store`, `tauri-plugin-deep-link`, and `tauri-plugin-notification` cover mobile too. The frontend can be vanilla JS / React / Vue / Svelte / Leptos / Dioxus.

Leptos, Dioxus, Yew, Sycamore — Rust full-stack frontends

WASM + Rust full-stack frameworks split four ways.

- **Leptos 0.7+**: signal-based fine-grained reactivity, first-class SSR / CSR / hydration / `server fn`. Full-stack build via `cargo-leptos`.

- **Dioxus 0.6+**: RSX (React-like) macro, multi-target — desktop / mobile / web / TUI. The Dioxus team turned full-time OSS in 2025.

- **Yew**: classic VDOM. Familiar onboarding but loses to Leptos on full-stack tooling.

- **Sycamore**: Solid-inspired signal-based. Good for learning / small SPAs.

A Leptos full-stack component example.

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(),

})}

}

}

The same screen in 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}" }

})

}

})

}

| Framework | Paradigm | Multi-target | Full-stack | Use when |

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

| Leptos | Signals, SSR-first | Web | Strong | Default full-stack web |

| Dioxus | RSX, multi-renderer | Web / desktop / mobile / TUI | In progress | Multi-target |

| Yew | VDOM | Web | Weak | Learning / simple SPAs |

| Sycamore | Signals | Web | Weak | Learning |

egui, Iced, Slint — native GUI libraries

If Tauri is "WebView-based," the native GUI side has three options.

- **egui**: immediate-mode GUI. Own renderer (`eframe`), short code, great for in-game UIs and internal tools.

- **Iced**: Elm-inspired, Cmd/Sub pattern. Desktop apps.

- **Slint**: DSL (`.slint` files). Embedded-friendly, with a commercial license available.

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 }))),

)

}

| Library | Paradigm | Renderer | Best for |

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

| egui | Immediate mode | wgpu / glow | In-game debug, internal tools |

| Iced | Elm-like retained | wgpu / tiny-skia | Desktop apps |

| Slint | DSL retained | software / skia / femtovg | Embedded, kiosks |

| Dioxus desktop | WebView | OS WebView | Web-asset reuse |

| Tauri 2 | WebView | OS WebView | Full desktop + mobile |

Bevy 0.15+ — the de-facto Rust game engine

Bevy is a data-oriented ECS game engine. In 0.15 (2025) it landed BSN (Bevy Scene Notation), render graph v2, and a UI overhaul; the 0.16 / 0.17 line in 2026 is adding the editor, hot reload, and more materials.

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's charm is that "ECS is a first-class citizen and systems are just functions." Beyond games, it sees growing adoption for simulations and tooling backends.

Embassy, RTIC, embedded-hal — embedded and firmware Rust

In `no_std` embedded land the 2026 story is clear. **Embassy is the de-facto standard**, while interrupt-priority-based deterministic systems still favor **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();

}

The `embedded-hal 1.0` release in late 2023 unified the driver ecosystem. Whether you target STM32 / RP2040 / nRF52 / ESP32, the same driver runs on any HAL implementing the `embedded-hal` traits.

CLI and system tools — clap 4.5, argh, ripgrep, bat, fd

For CLI parsers the de-facto standard is `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) keeps derive-macro compile time low and suits small tools. Among system command-line tools, Rust-written ones have become standard: `ripgrep`, `fd`, `bat`, `eza`, `zoxide`, `bottom`, `dust`, `procs`, `hyperfine`, `tokei`, `mdbook`.

Cargo workspaces, build.rs, cross-compilation

Large Rust projects bundle crates into a workspace.

Cargo.toml at the workspace root

[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"

For cross-compilation, the `cross` crate is the standard. `cross build --target aarch64-unknown-linux-musl --release` produces a static binary via a Dockerized toolchain.

Cargo tooling — nextest, mutants, deny, audit, machete, expand, binstall

Stock `cargo test` is no longer enough. The 2026 standard companion tools are:

| Tool | Purpose |

| --- | --- |

| cargo-nextest | Parallel test runner, polished output, isolation |

| cargo-mutants | Mutation testing for test-quality verification |

| cargo-deny | License / vulnerability / duplicate-dep checks |

| cargo-audit | RUSTSEC DB vulnerability scanner |

| cargo-machete | Detects unused dependencies |

| cargo-expand | View macro-expanded output |

| cargo-binstall | Install prebuilt binaries |

| cargo-watch | Auto-rebuild on file changes |

| cargo-leptos | Leptos full-stack build |

Standard CI bundle

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 has two camps.

- **Browser**: `wasm-bindgen` + `wasm-pack`. Automatic bindings between JS and Rust.

- **Server / edge**: `wasmtime` (Bytecode Alliance, sponsored by Fastly / Microsoft) and `wasmer`. WASI Preview 2 settled in 2024, and component-model-based modularization is rolling out.

Cloudflare Workers supports Rust + WASM as a first-class citizen, and companies like Fermyon, Spin, and WasmCloud are pulling WASM-based serverless forward.

rust-for-linux, Cloudflare Pingora, Discord, Dropbox, Figma — production stories

Rust adoption is no longer "the startup experiment."

| Company / project | When | Where Rust is used | Impact |

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

| Linux Kernel | Merged 2022, mainline expansion 2024 | Drivers, Android Binder | Systems-language certification |

| Cloudflare Pingora | Announced 2022, open-sourced 2024 | Next-gen HTTP proxy (NGINX replacement) | More than 40T requests/day |

| Discord | 2020 onward | Read States, gateway | GC pause eliminated, 99.99% reliability |

| Dropbox | 2014 onward | Magic Pocket storage | Exabyte scale |

| Figma | 2022 onward | Multiplayer HTTP layer | Concurrent edit performance |

| Mozilla / Servo | LF transfer 2024 | Next-gen browser engine | Embedded browser |

| AWS | Company-wide | Firecracker, Bottlerocket, parts of S3 | Containers / microVMs |

| Google | Android | Binder, crash subsystem | System memory safety |

| Microsoft | Windows | Selected system components | Memory-safety hardening |

| Meta | Backend | Parts of the service mesh | Officially adopted |

Pitfalls and trade-offs — easy traps when introducing Rust

Five traps we see when teams introduce Rust on a new project.

1. **Compile times**: full builds in a large workspace are long. The standard setup combines `cargo check`-centric workflow, `sccache`, the `mold` linker, and `debug-info=line-tables-only`.

2. **async + Send boundaries**: do not sprinkle `Box<dyn Trait>` everywhere. Library traits should declare `Send + 'static` bounds where realistic.

3. **dyn compatibility vs. RPITIT**: moving every async-trait method to RPITIT breaks dyn-trait usage. Traits used with `dyn` may still need the `async-trait` macro.

4. **Error-type explosion**: do not bake a giant `enum Error` into a single library. Use small per-module error types and lift them with `From`.

5. **unsafe overuse**: 99% of code does not need `unsafe`. If you are not doing FFI / embedded / SIMD, stop and revisit.

Korea and Japan — Rust adoption at Naver, Kakao, CyberAgent, Mercari, Sansan

Korea and Japan are equally active.

- **Naver**: parts of search / ad backends and media pipelines moved to Rust. Internal Rust study groups and seminars run on a recurring cadence.

- **Kakao Brain / Kakao Enterprise**: Rust for ML inference servers and model gateways, combined with Python via PyO3.

- **Discord Korea / Twitch Korea group**: relies on the global Rust stack as-is.

- **CyberAgent**: rewrote parts of ad and game infrastructure in Rust, including some AbemaTV microservices.

- **Mercari**: search, infra tools, and CLIs in Rust. Rust roles open continuously.

- **Sansan**: Rust in the business-card OCR post-processing pipeline.

- **LINE Yahoo**: system daemons and build tools migrated to Rust.

Both Tokyo and Seoul host quarterly Rust meetups. Korea has the "Rust Korea" Slack / Discord / Facebook groups; Japan has the recurring "Rust.Tokyo" conference.

A 2026 learning roadmap — what to study, in what order

A recommended flow for developers picking up Rust today.

1. **The Rust Programming Language ("the book")** chapters 1-10: build intuition for ownership, borrowing, and lifetimes.

2. **rustlings**: small fill-in-the-blank exercises to get comfortable with compiler messages.

3. **`cargo new` a CLI**: clap + serde + anyhow combo.

4. **A small API with tokio + axum**: sqlx + Postgres + tracing all the way through.

5. Study the **2024 edition changes and async fn in trait** explicitly.

6. Pick a domain:

- Web / full-stack: Leptos or Dioxus.

- Desktop: Tauri 2 or egui.

- Games: Bevy.

- Embedded: Embassy + RP2040 or STM32 Discovery.

- Systems: read the source of rust-for-linux, Firecracker, or Pingora.

The goal is not "write fast" — it is "talk with the compiler and build a model." Compiler errors are friends.

Wrap-up — in 2026 Rust is not "a choice" but "a default"

Connect the dots — rust-for-linux merged in 2024, Tauri 2 GA in 2024, Pingora open-sourced in 2025, axum 0.8 in 2025, Rust 1.85 / 2024 edition in 2026 — and the picture is clear. Backend defaults to tokio + axum + sqlx; desktop / mobile defaults to Tauri 2; games default to Bevy; embedded defaults to Embassy; full-stack web defaults to Leptos / Dioxus.

The question is no longer "should we use Rust?" but "where do we use Rust?" — and the answer keeps expanding.

References

- Rust official — https://www.rust-lang.org/

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

- Rust blog — 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 case study — https://discord.com/blog/why-discord-is-switching-from-go-to-rust

현재 단락 (1/494)

When the rust-for-linux patches were merged into the mainline kernel in late 2024, Rust crossed a li...

작성 글자: 0원문 글자: 24,623작성 단락: 0/494