Files
2nd/10_Wiki/Topics/Coding/Frontend_WASM_Integration.md
T
2026-05-09 21:08:02 +09:00

7.1 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
frontend-wasm-integration WebAssembly — Rust / Go / 통합 Coding draft B conceptual 2026-05-09 2026-05-09
frontend
wasm
rust
vibe-coding
language applicable_to
Rust / Go / TS
Frontend
Backend
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

# Setup
cargo new --lib my-wasm
cd my-wasm
# 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"
// 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::<f64>() / data.len() as f64;
    let variance = data.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / data.len() as f64;
    serde_wasm_bindgen::to_value(&Stats { mean, stddev: variance.sqrt() }).unwrap()
}

Build

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

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

// vite.config.ts
import wasm from 'vite-plugin-wasm';
import topLevelAwait from 'vite-plugin-top-level-await';

plugins: [wasm(), topLevelAwait()];
import init, { fibonacci } from './my_wasm';
await init();

Use case 1: Image processing

#[wasm_bindgen]
pub fn blur(data: &[u8], width: u32, height: u32, radius: u32) -> Vec<u8> {
    // Gaussian blur
    let img = image::RgbaImage::from_raw(width, height, data.to_vec()).unwrap();
    image::imageops::blur(&img, radius as f32).into_raw()
}
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)

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

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)

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

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)

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

# Wasmer / Wasmtime / Wasmer Edge
wasmer run my-app.wasm
// Cloudflare Workers + WASM
import wasmModule from './my_wasm.wasm';

export default {
  async fetch(req: Request): Promise<Response> {
    const instance = await WebAssembly.instantiate(wasmModule);
    return new Response(instance.exports.process(req));
  },
};

Component model (WIT)

// component.wit
interface processor {
    process: func(input: list<u8>) -> list<u8>
}

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

// 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;
}

디버그

// wasm-bindgen — console.log
import { console_log } from 'wasm-bindgen';

console_log!("debug");  // browser DevTools
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}
log("from rust");

Build size + perf flags

[profile.release]
opt-level = "z"      # size (또는 3 = speed)
lto = true
codegen-units = 1
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 만.

🔗 관련 문서