--- id: frontend-wasm-integration title: WebAssembly — Rust / Go / 통합 category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [frontend, wasm, rust, vibe-coding] tech_stack: { language: "Rust / Go / TS", applicable_to: ["Frontend", "Backend"] } applied_in: [] aliases: [WASM, WebAssembly, Rust wasm-bindgen, AssemblyScript, Wasmer, WIT] --- # WebAssembly > JS 안 빠른 / native lib 사용. **Rust + wasm-bindgen 표준**. ML inference, image / video 처리, crypto, parser, regex. Browser + Node + Cloudflare Workers + WASI. ## 📖 핵심 개념 - WASM: Binary instruction format. - wasm-bindgen: Rust ↔ JS 자동 binding. - WASI: WASM 의 system interface (file, network). - WIT (WebAssembly Interface Types): cross-language. ## 💻 코드 패턴 ### Rust → WASM ```bash # Setup cargo new --lib my-wasm cd my-wasm ``` ```toml # Cargo.toml [package] name = "my-wasm" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2" serde = { version = "1", features = ["derive"] } serde-wasm-bindgen = "0.6" ``` ```rust // src/lib.rs use wasm_bindgen::prelude::*; use serde::{Serialize, Deserialize}; #[wasm_bindgen] pub fn fibonacci(n: u32) -> u64 { let mut a: u64 = 0; let mut b: u64 = 1; for _ in 0..n { let c = a + b; a = b; b = c; } a } #[derive(Serialize, Deserialize)] pub struct Stats { mean: f64, stddev: f64 } #[wasm_bindgen] pub fn analyze(data: &[f64]) -> JsValue { let mean = data.iter().sum::() / data.len() as f64; let variance = data.iter().map(|x| (x - mean).powi(2)).sum::() / data.len() as f64; serde_wasm_bindgen::to_value(&Stats { mean, stddev: variance.sqrt() }).unwrap() } ``` ### Build ```bash # wasm-pack cargo install wasm-pack wasm-pack build --target web # 또는 bundler 통합 wasm-pack build --target bundler # Output: pkg/ folder with .wasm + JS glue ``` ### Use (browser) ```ts import init, { fibonacci, analyze } from './pkg/my_wasm'; await init(); // load .wasm console.log(fibonacci(50)); // 12586269025 console.log(analyze([1.0, 2.0, 3.0])); // { mean: 2, stddev: 0.816 } ``` ### Vite plugin ```ts // vite.config.ts import wasm from 'vite-plugin-wasm'; import topLevelAwait from 'vite-plugin-top-level-await'; plugins: [wasm(), topLevelAwait()]; ``` ```ts import init, { fibonacci } from './my_wasm'; await init(); ``` ### Use case 1: Image processing ```rust #[wasm_bindgen] pub fn blur(data: &[u8], width: u32, height: u32, radius: u32) -> Vec { // Gaussian blur let img = image::RgbaImage::from_raw(width, height, data.to_vec()).unwrap(); image::imageops::blur(&img, radius as f32).into_raw() } ``` ```ts const ctx = canvas.getContext('2d')!; const imageData = ctx.getImageData(0, 0, w, h); const blurred = blur(imageData.data, w, h, 5); ctx.putImageData(new ImageData(new Uint8ClampedArray(blurred), w, h), 0, 0); ``` ### ML inference (ONNX Runtime Web) ```ts import * as ort from 'onnxruntime-web'; const session = await ort.InferenceSession.create('/model.onnx'); const tensor = new ort.Tensor('float32', input, [1, 3, 224, 224]); const result = await session.run({ input: tensor }); ``` → ResNet / YOLO 같은 모델 browser 안. ### Transformers.js ```ts import { pipeline } from '@xenova/transformers'; const pipe = await pipeline('text-classification', 'Xenova/distilbert-base-uncased-finetuned-sst-2-english'); const out = await pipe('I love this!'); // [{ label: 'POSITIVE', score: 0.999 }] ``` → Hugging Face 모델 browser 직접. ### TensorFlow.js (WebGL / WebGPU) ```ts import * as tf from '@tensorflow/tfjs'; const model = await tf.loadLayersModel('/model.json'); const tensor = tf.tensor(input).reshape([1, 224, 224, 3]); const pred = model.predict(tensor) as tf.Tensor; ``` ### SQLite — sql.js / wasm-sqlite ```ts import initSqlJs from 'sql.js'; const SQL = await initSqlJs({ locateFile: f => `/sql-wasm.wasm` }); const db = new SQL.Database(); db.run('CREATE TABLE users (id INTEGER, name TEXT)'); db.run('INSERT INTO users VALUES (?, ?)', [1, 'Alice']); const result = db.exec('SELECT * FROM users'); ``` → Browser 안 SQLite. ### Worker + WASM (offload main thread) ```ts // worker.ts import init, { heavyWork } from './my_wasm'; self.onmessage = async (e) => { await init(); const result = heavyWork(e.data); self.postMessage(result); }; // main.ts const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' }); worker.postMessage(input); worker.onmessage = (e) => console.log(e.data); ``` ### WASI (server-side WASM) ```bash # Wasmer / Wasmtime / Wasmer Edge wasmer run my-app.wasm ``` ```ts // Cloudflare Workers + WASM import wasmModule from './my_wasm.wasm'; export default { async fetch(req: Request): Promise { const instance = await WebAssembly.instantiate(wasmModule); return new Response(instance.exports.process(req)); }, }; ``` ### Component model (WIT) ```wit // component.wit interface processor { process: func(input: list) -> list } ``` → Cross-language WASM components. ### Performance vs JS ``` 간단 작업 (sum, fib): JS engine 도 빠름 — WASM 비슷 복잡 / 메모리 intensive (image, ML, parser): WASM 5-50x 빠름 SIMD 가능: WASM 더 빠름 GC 객체 (string, array): JS ↔ WASM boundary 비용 ``` → Hot path + 큰 데이터 = WASM. 일반 = JS. ### Bundle size ``` Rust + wasm-bindgen: 100KB-1MB 일반 + Streaming compile (instantiateStreaming) — 빠른 load wasm-opt 로 size 줄이기. ``` ### AssemblyScript (TS-like → WASM) ```ts // Rust 보다 친숙. 단 ecosystem 작음. export function fibonacci(n: i32): i64 { let a: i64 = 0, b: i64 = 1; for (let i = 0; i < n; i++) { const c = a + b; a = b; b = c; } return a; } ``` ### 디버그 ```ts // wasm-bindgen — console.log import { console_log } from 'wasm-bindgen'; console_log!("debug"); // browser DevTools ``` ```rust #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] fn log(s: &str); } log("from rust"); ``` ### Build size + perf flags ```toml [profile.release] opt-level = "z" # size (또는 3 = speed) lto = true codegen-units = 1 ``` ```bash wasm-opt -Oz -o optimized.wasm input.wasm ``` ## 🤔 의사결정 기준 | 작업 | 추천 | |---|---| | Browser ML | Transformers.js / ONNX Runtime Web | | 이미지 처리 (blur, resize) | Rust + wasm-bindgen | | Crypto / hashing | WASM | | SQL in browser | sql.js | | Edge function (CF Workers) | WASM 가능 | | 일반 logic | JS — overhead 안 worth | ## ❌ 안티패턴 - **작은 작업 WASM**: JS-WASM boundary 비용 > 절약. - **Streaming compile 안 함**: 큰 .wasm 늦은 load. - **Memory copy 매 호출**: 큰 data — typed array share. - **Single-thread WASM main**: UI block. Worker. - **WASM bundle 분리 X**: 첫 load 큼. Dynamic import. - **Debug build prod**: 5-10x 큰. release. - **JS-WASM circular call**: stack / boundary 비용. ## 🤖 LLM 활용 힌트 - Rust + wasm-bindgen + wasm-pack = 표준. - Vite plugin-wasm + top-level-await. - Worker 안 WASM + transferable data. - Hot path / 큰 data 만. ## 🔗 관련 문서 - [[Web_OffMain_WebWorker]] - [[Perf_V8_Optimization]] - [[AI_Local_LLM_Inference]]