WebAssembly(Wasm)는 브라우저에서 네이티브에 가까운 속도로 실행되는 바이너리 포맷입니다. C, C++, Rust 같은 언어로 작성한 코드를 컴파일하여 JavaScript와 함께 사용할 수 있습니다.

WebAssembly란?

PLAINTEXT
고수준 언어 (C/C++/Rust)
    ↓ 컴파일러 (Emscripten, wasm-pack)
WebAssembly (.wasm 바이너리)
    ↓ 브라우저 로드
JavaScript에서 호출

Wasm이 JavaScript보다 빠른 이유:

  • 바이너리 형식 → 파싱 비용 최소
  • 정적 타입 → 타입 체크 오버헤드 없음
  • 메모리를 직접 관리 → GC 없음
  • SIMD 같은 저수준 최적화 가능

Wasm 모듈 로드

JS
// 방법 1: 스트리밍 컴파일 (권장)
const response = await fetch("module.wasm");
const { instance } = await WebAssembly.instantiateStreaming(response, {
  env: {
    // JS에서 Wasm으로 전달하는 함수
    log: (value) => console.log("Wasm:", value),
  },
});

// 익스포트된 함수 호출
const result = instance.exports.add(40, 2);
console.log(result); // 42

// 방법 2: ArrayBuffer에서 컴파일
const buffer = await fetch("module.wasm").then((r) => r.arrayBuffer());
const module = await WebAssembly.compile(buffer);
const instance2 = await WebAssembly.instantiate(module);

WAT로 이해하는 Wasm

Wasm의 텍스트 표현(WAT)으로 간단한 모듈을 살펴봅니다.

WAT
;; add.wat — 두 수를 더하는 Wasm 모듈
(module
  (func $add (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add)
  (export "add" (func $add)))

메모리 공유

JS
// Wasm 메모리 생성
const memory = new WebAssembly.Memory({
  initial: 1,  // 1페이지 = 64KB
  maximum: 10, // 최대 10페이지
});

// JavaScript에서 Wasm 메모리 접근
const view = new Uint8Array(memory.buffer);
view[0] = 42;

// 문자열 전달 (메모리에 직접 쓰기)
function writeString(memory, offset, str) {
  const encoder = new TextEncoder();
  const bytes = encoder.encode(str);
  const view = new Uint8Array(memory.buffer);
  view.set(bytes, offset);
  return bytes.length;
}

function readString(memory, offset, length) {
  const decoder = new TextDecoder();
  const view = new Uint8Array(memory.buffer, offset, length);
  return decoder.decode(view);
}

Rust에서 Wasm으로

RUST
// Rust 코드 (wasm-bindgen 사용)
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    if n <= 1 { return n; }
    fibonacci(n - 1) + fibonacci(n - 2)
}
JS
// JavaScript에서 호출
import init, { fibonacci } from "./pkg/my_wasm.js";

await init();
console.log(fibonacci(40)); // Rust 컴파일된 코드로 빠르게 실행

성능 비교

JS
// JavaScript 피보나치
function jsFibonacci(n) {
  if (n <= 1) return n;
  return jsFibonacci(n - 1) + jsFibonacci(n - 2);
}

// 벤치마크
console.time("JS");
jsFibonacci(40);
console.timeEnd("JS"); // ~1500ms

console.time("Wasm");
wasmFibonacci(40);
console.timeEnd("Wasm"); // ~300ms (약 5배 빠름)

Wasm이 적합한 경우

적합부적합
무거운 수학 연산DOM 조작
이미지/비디오 처리일반 웹 UI
게임 엔진간단한 CRUD
암호화/압축API 호출
과학 시뮬레이션일반 비즈니스 로직

WASI — 서버 사이드 Wasm

JS
// WASI (WebAssembly System Interface) — 브라우저 밖에서 Wasm 실행
// 파일 시스템, 네트워크 등 시스템 인터페이스 제공
// Node.js에서도 실험적으로 지원

import { WASI } from "wasi";
const wasi = new WASI({ args: [], env: {} });
const module = await WebAssembly.compile(wasmBuffer);
const instance = await WebAssembly.instantiate(module, {
  wasi_snapshot_preview1: wasi.wasiImport,
});
wasi.start(instance);

**기억하기 **: WebAssembly는 JavaScript를 대체하는 것이 아니라 ** 보완 **하는 기술입니다. 무거운 연산(이미지 처리, 게임, 암호화)은 Wasm으로, UI와 DOM 조작은 JavaScript로 처리하는 것이 최적의 조합입니다. Rust + wasm-bindgen 조합이 가장 인기 있는 Wasm 개발 스택입니다.

댓글 로딩 중...