- Published on
WebAssembly 서버사이드와 WASI 2026 심층 분석 - Spin, Wasmtime, Wasmer, WasmEdge, wasmCloud, Extism, JCO, Component Model 완전 가이드
- Authors

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — 2026년, WASM은 "브라우저의 빠른 어셈블리"가 아니다
2019년 솔로몬 하이크스(Solomon Hykes, Docker 창업자)가 트위터에 남긴 한 줄은 이제 인용 너머의 현실이 됐다.
"If WASM+WASI existed in 2008, we wouldn't have needed to create Docker."
2026년의 WebAssembly는 다음과 같다.
- WASI Preview 2가 2024년 1월 정식 릴리스됐고, 2025년 내내 런타임들이 P2 호환을 마쳤다. Wasmtime 26+, WasmEdge 0.14+, Wasmer 5+, jco 1.x가 모두 P2 컴포넌트를 실행한다.
- Component Model이 안정화되면서 Rust·Go·JavaScript·Python·Java로 작성한 코드가 단일 WIT 인터페이스를 통해 조립된다. polyglot은 더 이상 슬로건이 아니라 표준이다.
- 엣지 컴퓨트에서 WASM은 V8 isolate를 잇는 차세대 격리 기술이 됐다. Cloudflare Workers는 WASM 바인딩을 1급으로 지원하고, Fastly Compute@Edge는 처음부터 WASM 위에 만들어졌고, Cosmonic·Fermyon Cloud·Wasmer Edge가 전용 WASM PaaS로 성장했다.
- Docker Desktop은 WASM 워크로드를 정식 지원하며
docker run --runtime=io.containerd.wasmedge.v1한 줄로 컨테이너 없이 WASM을 띄운다. Kubernetes는 RuntimeClass와 spin-operator로 WASM 워크로드를 노드에 스케줄한다. - 임베디드와 IoT에서도 WASM은 OTA 업데이트 가능한 안전한 플러그인 모델로 자리잡았다. Extism이 그 기수다.
이 글은 그 변화의 한복판을 24-28개 챕터로 정리한다. 코드는 모두 2026년 5월 기준 실제로 동작하는 형태이고, 인용된 URL은 모두 실제 문서다.
한 줄 요약: "내 코드는 어디서 어떤 권한으로 실행되는가, 그리고 그것을 누가 조립하는가" — 이 두 질문이 2026년 WASM 도구 선택의 90%를 결정한다.
1장 · WASM의 본질 다시 보기 — 어셈블리, 격리, 이식
WebAssembly는 자주 "빠른 어셈블리"로 소개되지만, 실제 본질은 세 가지 축이다.
| 축 | 의미 | 결과 |
|---|---|---|
| Portable bytecode | 스택 머신 기반의 가상 ISA | 어디서나 같은 바이너리 |
| Sandboxed by default | 호스트 메모리·시스템콜에 직접 접근 불가 | 신뢰 경계 명확 |
| Deterministic | 부동소수점 NaN 비결정성을 빼면 결정적 | 캐싱·재현성 우수 |
브라우저는 그 첫 무대였을 뿐이다. 2017년 MVP 이후 WASM 코어 사양은 reference types, multi-value, bulk memory, SIMD, threads, tail call, GC, exception handling, multi-memory, function references까지 확장됐다. 2026년 현재 GC와 exception handling이 모든 메이저 런타임에서 안정화됐고, 이 위에서 Java·Kotlin·OCaml·Dart 같은 GC 언어들이 자연스럽게 컴파일된다.
중요한 인식 전환: 2026년의 WASM은 "C/Rust를 빠르게 돌리는 가상 머신"이 아니라 **"언어 중립의 컴포넌트 ABI"**다. 그래서 다음 장의 Component Model이 본질이다.
2장 · WASI Preview 1 vs Preview 2 — POSIX 모방에서 캐퍼빌리티 인터페이스로
초기의 WASI(WebAssembly System Interface)는 POSIX의 부분 모방이었다. fd_read, fd_write, path_open 같은 함수가 wasi_snapshot_preview1 인터페이스에 평탄하게 나열돼 있었고, Rust의 wasm32-wasi 타깃이 그것을 호출했다. 사실상 "런타임이 빌려준 POSIX"였다.
WASI Preview 2(WASI 0.2)는 다르다.
- 모든 인터페이스가 **WIT(WebAssembly Interface Type)**로 기술된다. 평탄한 함수 목록이 아니라 interface와 world의 계층 구조다.
- 표준 P2 worlds:
wasi:cli/command,wasi:http/proxy,wasi:keyvalue/store,wasi:filesystem/types,wasi:sockets/network,wasi:logging/logging,wasi:clocks/wall-clock,wasi:random/random. - 각 world는 호스트가 명시적으로 import한 권한만 모듈에 노출한다. 모듈이 호스트 디스크를 보려면 호스트가
wasi:filesystem을 명시적으로 연결해야 한다.
이것이 곧 캐퍼빌리티 기반 보안(capability-based security) 이다. ambient authority(주변에 떠다니는 권한)는 없다. 모듈은 자기가 "import한 것"만 할 수 있다. 컨테이너의 seccomp/capabilities/AppArmor보다 훨씬 명시적이고 컴포저블하다.
P1 → P2 마이그레이션은 2025년에 대부분 끝났다. Rust의 wasm32-wasip2 타깃, TinyGo의 wasip2, jco의 P2 컴포넌트 생성이 표준 경로다.
3장 · Component Model — 언어 중립 ABI라는 사건
Component Model은 WASM에 두 층을 추가한다.
- Core module — 기존의 .wasm. 함수, 메모리, 테이블, 전역.
- Component — 여러 core module을 묶고, WIT 타입(record, variant, list, option, result, resource, tuple, string)을 외부 인터페이스로 노출.
Component Model이 해결한 것은 언어 사이의 ABI 협상이다. C와 Rust는 메모리를 직접 다룬다. Go는 GC를 가진다. JavaScript는 GC + JIT다. 이들이 함수를 직접 호출할 수 없다. Component Model은 그 중간에 canonical ABI를 두고, lift/lower 연산으로 타입을 변환한다.
WIT 인터페이스 정의 한 조각을 보자.
package example:greeter@0.2.0;
interface api {
/// 인사말을 만든다.
greet: func(name: string) -> string;
/// 카운터 리소스.
resource counter {
constructor();
increment: func();
get: func() -> u64;
}
}
world greeter {
export api;
import wasi:clocks/wall-clock@0.2.0;
import wasi:logging/logging@0.2.0;
}
이 WIT 한 파일로:
- Rust에서
wit-bindgen매크로가 트레이트와 구현 스텁을 만든다. - JavaScript에서
jco transpile이 ES 모듈을 만든다. - Go에서
wit-bindgen-go가 Go 패키지를 생성한다. - Python에서
componentize-py가 Python 코드를 WASM으로 묶는다.
호출자는 어떤 언어로 구현됐는지 모른다. 그것이 컴포넌트 모델의 약속이다.
4장 · Wasmtime — Bytecode Alliance의 레퍼런스 런타임
Wasmtime은 Bytecode Alliance가 만드는 WASM의 사실상 레퍼런스 구현이다. Rust로 작성됐고, Cranelift 코드젠을 통해 x86_64/aarch64/s390x로 AOT/JIT 컴파일한다.
2026년 현재 Wasmtime 26.x가 안정 버전이다. 주요 특징:
- WASI Preview 2 full support — wasmtime-wasi 크레이트.
- Component Model first-class — wasmtime-component 크레이트.
- Pooling allocator — 수만 개의 인스턴스를 동시에 띄울 때 메모리 단편화 없이 재사용.
- Epoch-based interruption — 무한 루프를 외부에서 중단.
- Pre-compilation(.cwasm) — AOT로 미리 컴파일해 콜드스타트 ~수십 마이크로초.
- Async support — Tokio와 매끄러운 통합.
Wasmtime의 정수는 호스트 임베딩이 깔끔하다는 점이다. Rust 호스트가 컴포넌트를 로드해 함수를 호출하는 흐름:
use wasmtime::{Engine, Config, Store};
use wasmtime::component::{Component, Linker};
fn main() -> anyhow::Result<()> {
let mut config = Config::new();
config.wasm_component_model(true);
config.async_support(false);
let engine = Engine::new(&config)?;
let component = Component::from_file(&engine, "greeter.wasm")?;
let mut linker = Linker::new(&engine);
wasmtime_wasi::add_to_linker_sync(&mut linker)?;
let wasi = wasmtime_wasi::WasiCtxBuilder::new()
.inherit_stdio()
.build_p1();
let mut store = Store::new(&engine, wasi);
let instance = linker.instantiate(&mut store, &component)?;
let greet = instance.get_typed_func::<(String,), (String,)>(&mut store, "greet")?;
let (out,) = greet.call(&mut store, ("WASI 2026".into(),))?;
println!("{out}");
Ok(())
}
이 패턴은 Spin·wasmCloud·Lambda Adapter가 모두 내부적으로 변주한다.
5장 · Wasmer — 멀티 백엔드와 패키지 매니저로서의 WASM
Wasmer는 Wasmtime과 결이 다르다. 처음부터 여러 컴파일러 백엔드(Cranelift, LLVM, Singlepass)를 골라 쓸 수 있게 만들었고, WAPM(WebAssembly Package Manager)을 통해 npm-like한 배포 채널을 가졌다.
2026년의 Wasmer 5.x는 다음에 강점이 있다.
- LLVM 백엔드의 최대 성능 — 네이티브 코드 대비 90% 수준.
- WASIX — Preview 1을 확장해 스레드, 시그널, fork, exec, TCP/UDP socket까지 지원하는 자체 사양. POSIX 앱을 거의 그대로 돌릴 수 있다. Python·Bash·Postgres를 Wasmer에서 돌리는 데모가 유명하다.
- Wasmer Edge — Cloudflare Workers와 경쟁하는 자체 엣지 PaaS.
- JS·Python·PHP 통합 — Wasmer의 SDK는 호스트 언어를 가리지 않는다.
Wasmer로 Python을 돌리는 한 줄:
wasmer run python/python --mapdir=/app:./app -- /app/main.py
WAPM은 컴포넌트 모델 위에 패키지를 묶는다. 2026년 들어 OCI 레지스트리(GHCR, Docker Hub)와의 상호운용이 가속됐고, ghcr.io에 WASM 컴포넌트를 푸시하는 표준 흐름이 자리잡았다.
Wasmer의 P2 지원은 Wasmtime보다 약간 늦었지만 5.x에서 따라잡았다. WASIX와 P2를 한 런타임이 모두 다루는 점이 Wasmer의 차별점이다.
6장 · WasmEdge — 클라우드 네이티브와 AI에 특화한 런타임
WasmEdge는 CNCF Sandbox에서 Incubating을 거쳐 2025년 Graduated에 가까운 위상을 얻었다. CloudOS·CDN·AI 인퍼런스에 특화된 설계가 특징이다.
- AOT(Ahead-Of-Time) 컴파일 — LLVM 기반. 콜드스타트가 사실상 0에 가깝다.
- Kubernetes 워크로드 1급 지원 — containerd-wasm-shims, CRI-O, Docker Desktop, Kubernetes RuntimeClass.
- AI 플러그인 — WasmEdge ggml(llama.cpp 백엔드), PyTorch, TensorFlow Lite, OpenVINO. Llama 3·Mistral·Qwen을 WasmEdge로 직접 추론한다.
- 네트워킹 확장 — TLS, HTTP/2, QUIC를 호스트가 제공한다.
- 언어 SDK — Rust, C, Go, Java, Python, JavaScript(QuickJS 통합).
Docker Desktop 4.x 이후 WasmEdge는 "docker run --runtime=io.containerd.wasmedge.v1" 한 줄로 실행된다. Kubernetes에서는 다음과 같이 RuntimeClass를 정의한다.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: wasmedge
handler: wasmedge
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-wasm
spec:
replicas: 3
selector:
matchLabels: { app: hello-wasm }
template:
metadata:
labels: { app: hello-wasm }
spec:
runtimeClassName: wasmedge
containers:
- name: hello
image: ghcr.io/example/hello-wasm:0.1.0
WasmEdge는 "K8s에서 WASM 돌리는 가장 쉬운 길"이라는 포지셔닝이 명확하다.
7장 · Spin(Fermyon) — WASM 마이크로서비스 프레임워크
Fermyon의 Spin은 "WASM 위의 Express/Flask"라고 부를 수 있다. 컴포넌트 한 개가 HTTP 핸들러·Redis 컨슈머·Cron 트리거 등으로 동작하며, 컴포넌트 사이는 WIT로 연결된다.
Spin의 핵심 구성요소:
- spin.toml — 매니페스트.
- trigger — http, redis, mqtt, cron, sqs, kafka.
- wasi-keyvalue, wasi-sqlite, wasi-llm — Spin이 호스트가 되어 제공하는 P2 인터페이스.
- Spin SDK — Rust, Go, JS/TS, Python, .NET, Java.
가장 간단한 HTTP 컴포넌트의 매니페스트:
spin_manifest_version = 2
[application]
name = "hello-spin"
version = "0.1.0"
[[trigger.http]]
route = "/hello/..."
component = "hello"
[component.hello]
source = "target/wasm32-wasip2/release/hello.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
key_value_stores = ["default"]
sqlite_databases = ["default"]
[component.hello.build]
command = "cargo build --target wasm32-wasip2 --release"
watch = ["src/**/*.rs", "Cargo.toml"]
Spin은 단일 바이너리(spin up)로 로컬에서 돌고, Fermyon Cloud나 Fermyon Platform for Kubernetes(spin-operator)로 배포한다. 한 마디로 "WASM 네이티브 마이크로서비스 운영체계"다.
2026년 들어 Spin은 LangChain·LlamaIndex 풍의 AI 워크플로(spin-llm)와 통합하면서 엣지 AI 서버 카테고리로 확장됐다.
8장 · wasmCloud — 분산 액터 모델 위의 WASM
wasmCloud는 CNCF Incubating 프로젝트로, "WASM 컴포넌트 + 액터 모델 + NATS 메시징"을 한 묶음으로 제공한다. 핵심 아이디어:
- 모든 비즈니스 로직은 **컴포넌트(actor)**다. 컴포넌트는 WIT 인터페이스만 안다.
- 외부 시스템(DB, HTTP, 키밸류, blob)은 **provider(capability provider)**가 책임진다.
- 둘 사이를 lattice(NATS 위에 만든 가상 네트워크)가 라우팅한다.
이게 곧 의존성 역전이다. 컴포넌트는 "Redis를 호출"하지 않고 "wasi:keyvalue/store를 호출"한다. 그 실체가 Redis인지 NATS KV인지 Postgres인지는 운영자가 wadm(wasmCloud Application Deployment Manager)에서 바인딩한다.
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: hello-wasmcloud
spec:
components:
- name: hello
type: component
properties:
image: ghcr.io/example/hello:0.1.0
traits:
- type: spreadscaler
properties:
instances: 5
- type: link
properties:
target: redis-kv
namespace: wasi
package: keyvalue
interfaces: ["store"]
- name: redis-kv
type: capability
properties:
image: ghcr.io/wasmcloud/redis-kv:0.10.0
여러 클라우드·엣지·온프레미스에 같은 lattice를 확장할 수 있다는 점이 wasmCloud의 자랑이다. Adobe·BMW·Bosch가 컨퍼런스 사례로 자주 등장한다.
9장 · Lunatic — Erlang/Elixir 영감의 WASM 런타임
Lunatic은 BEAM(Erlang VM)의 액터·슈퍼바이저 트리·preemptive scheduling 아이디어를 WASM에 옮긴 런타임이다. Rust로 만들어졌고, Wasmtime을 코어로 활용한다.
- 수십만 개의 경량 프로세스를 한 노드에서 띄운다.
- OTP-스타일 supervisor가 자식 프로세스를 감시한다.
- 메시지 패싱 만으로 통신. 공유 메모리 없음.
- distributed mode로 노드 간 메시징.
특화된 영역은 다음과 같다.
- 동시성이 핵심인 게임 서버, 채팅, 협업 도구.
- 장시간 살아있어야 하는 워크플로 엔진.
- 작은 단위로 격리되어야 하는 멀티테넌트 SaaS.
Spin이 "HTTP 핸들러 묶음"에 가깝다면 Lunatic은 "WASM 위의 BEAM"이다. 두 도구는 경쟁이 아니라 다른 사용처에 산다.
10장 · Extism — 호스트 앱에 WASM 플러그인을 박는 표준
Extism은 "내 앱을 WASM 플러그인으로 확장하고 싶다"는 단 하나의 문제에 집중한다. Dylibso가 OSS로 만든다.
- 호스트 SDK: C, Rust, Go, JavaScript(Node·Browser), Python, Ruby, PHP, .NET, Java, Zig, Haskell, Elixir, OCaml.
- 플러그인 SDK(PDK): Rust, Go, AssemblyScript, JS, Zig, C, Haskell.
- 인터페이스는 WASM 함수 + 메모리 + 호스트 함수. 컴포넌트 모델보다 단순한 ABI.
대표 시나리오:
- 데이터베이스/큐의 사용자 정의 함수 — Cloudflare D1, Materialize, Tessera 같은 시스템이 사용자 코드를 안전하게 실행.
- CMS·SaaS의 확장점 — Sanity, GitHub Actions, 사내 워크플로 엔진.
- CLI 도구의 플러그인 —
awscli,kubectl,terraform이 외부 코드 동작을 안전하게 추가.
Extism은 컴포넌트 모델의 일반성을 일부 양보하고, 호스트 통합의 단순성을 택했다. 2026년에는 Extism 1.x가 안정 버전이고, OCI 레지스트리에서 플러그인을 가져오는 extism call oci://... 흐름이 표준이다.
11장 · JCO와 StarlingMonkey — JavaScript도 컴포넌트가 된다
JCO(JavaScript Component Object)는 Bytecode Alliance가 만든 JavaScript ↔ Component 변환 도구다. 2026년 jco 1.x가 안정 버전이다.
핵심 기능:
jco componentize app.js --wit ./wit -o app.wasm— JavaScript를 StarlingMonkey(SpiderMonkey 기반 임베디드 JS 엔진)로 묶어 단일 컴포넌트 .wasm을 만든다.jco transpile component.wasm -o ./out— 컴포넌트를 Node.js/브라우저에서 임포트할 수 있는 ES 모듈로 변환.jco run app.wasm— Node 위에서 P2 컴포넌트를 직접 실행.
StarlingMonkey는 Mozilla의 SpiderMonkey를 임베디드 형태로 잘라낸 것으로, Cloudflare workerd 다음 세대의 JS-on-WASM 런타임이다. Fastly Compute, Fermyon Spin이 JS 컴포넌트의 런타임으로 StarlingMonkey를 채택했다.
JCO의 진가는 TypeScript 타입 자동 생성이다. WIT 파일에서 .d.ts를 만들어 호출 측이 컴포넌트의 모든 함수·리소스에 타입 안전하게 접근한다.
// app.js — JCO로 componentize되는 코드
import { now } from 'wasi:clocks/wall-clock@0.2.0';
import { log } from 'wasi:logging/logging@0.2.0';
export const api = {
greet(name) {
const { seconds } = now();
log('info', 'greeter', `now=${seconds}`);
return `Hello, ${name}! It is now ${seconds}.`;
},
};
이 한 파일이 jco를 거쳐 어떤 호스트(Wasmtime, Spin, wasmCloud, Cloudflare Workers)에서도 실행 가능한 컴포넌트가 된다.
12장 · 폴리글랏 컴파일 경로 — Rust, Go, C/C++, AssemblyScript, Python, Java, .NET
각 언어의 2026년 표준 컴파일 경로를 짧게 정리한다.
| 언어 | 도구 | 타깃 | 비고 |
|---|---|---|---|
| Rust | rustc + cargo-component | wasm32-wasip2 | 1급 지원, 최단 경로 |
| C/C++ | wasi-sdk(clang 19+) | wasm32-wasip2 | wit-bindgen-c로 컴포넌트화 |
| Go | TinyGo 0.34+ | wasip2 | 표준 Go도 wasip1 지원, wasip2는 TinyGo가 빠름 |
| AssemblyScript | asc 0.27+ | wasm32 | TS-like 문법, 작은 바이너리 |
| JavaScript | jco + StarlingMonkey | component | 12장 참고 |
| Python | componentize-py | component | CPython을 WASM으로 묶음 |
| Java | TeaVM, CheerpJ, Spasm | wasm32-gc | JVM 바이트코드를 WASM-GC로 |
| C# / .NET | wasi-experimental + NativeAOT | wasi | .NET 9에서 WASI P2 정식화 진행 |
| Ruby | ruby.wasm | wasi | Ruby 3.3+ 공식 WASM 빌드 |
| Zig | zig build -target wasm32-wasi | wasi | 컴포넌트 모델은 wasm-tools로 |
특히 Python·Java·.NET이 컴포넌트화 가능해진 것이 2024-2025년의 큰 변화다. "C/Rust만의 영역"이라는 인식은 이제 옛말이다.
13장 · WIT와 wit-bindgen — 인터페이스 우선 개발
Component Model의 진짜 일하는 방식은 "먼저 WIT를 쓰고, 그 다음 구현 언어를 고른다"는 흐름이다.
wit-bindgen은 WIT를 읽어 각 언어의 바인딩을 만든다. Rust 예시:
wit_bindgen::generate!({
world: "greeter",
path: "./wit",
});
use exports::example::greeter::api::Guest;
struct Component;
impl Guest for Component {
fn greet(name: String) -> String {
format!("Hello, {name} from Rust WASM!")
}
}
export!(Component);
빌드는 wasm-tools로 컴포넌트화한다.
cargo build --target wasm32-wasip2 --release
wasm-tools component new \
target/wasm32-wasip2/release/greeter.wasm \
-o greeter.component.wasm
wasm-tools validate greeter.component.wasm
생성된 greeter.component.wasm은 Wasmtime, Spin, jco, wasmCloud 어디서나 같다. 이것이 컴포넌트 모델의 약속이다.
14장 · Cloudflare Workers와 WASM — V8 isolate 위의 모듈
Cloudflare Workers는 V8 isolate를 기본 격리 단위로 쓰면서 WASM을 1급 모듈로 지원한다.
wrangler.toml의[[rules]]+type = "CompiledWasm"으로 WASM 바인딩.- JS Worker가 WASM 모듈의 export를 직접 호출.
- 메모리 32MB·CPU 50ms(무료) / 30s(유료) 제한.
- 2025년 들어 WASI Preview 2 컴포넌트의 직접 실행도 베타로 등장했다 — 기존엔 JS shim이 필요했다.
전형적인 Rust → WASM → Workers 흐름:
cargo install wasm-pack
wasm-pack build --target web
wrangler deploy
Workers는 강력하지만 컴포넌트 모델의 모든 측면(예: 임의 host import)을 지원하진 않는다. Cloudflare가 자체적으로 빌트인 바인딩(KV, R2, D1, Queues, AI, Durable Objects)을 제공하는 식이다.
15장 · Fastly Compute@Edge — WASM-first 엣지의 원형
Fastly Compute@Edge는 처음부터 WASM(Wasmtime 기반) 위에 만들어진 엣지 플랫폼이다. V8 isolate를 거치지 않고 직접 WASM 인스턴스를 띄운다.
- 콜드스타트 < 1ms — pre-instantiation 덕분.
- Rust, JS, Go(TinyGo), AssemblyScript SDK 1급 지원.
- ESI(Edge Side Includes), KV Store, Config Store, Object Store, Secret Store.
- 2025년 P2 컴포넌트 정식 채택, 2026년 jco로 만든 JS 컴포넌트 직접 실행.
Fastly의 강점은 로깅·실시간 메트릭의 풍성함과 SOC2/PCI/HIPAA 인증 범위다. 미디어·e-커머스·금융 서비스가 Fastly Compute에 많이 산다.
16장 · AWS Lambda Web Adapter와 WASM — 람다에서 컴포넌트 돌리기
AWS Lambda는 2026년 현재 공식 WASM 런타임을 가지지는 않는다. 대신 두 우회로가 표준이다.
- AWS Lambda Web Adapter — Lambda 위의 컨테이너 이미지 안에 Wasmtime을 띄우고 컴포넌트를 실행.
awslabs/aws-lambda-web-adapterGitHub 저장소. - Fermyon Spin + Lambda — Spin 컴포넌트를 Lambda Adapter로 감싸 배포.
Lambda의 콜드스타트 350ms vs Wasmtime의 µs 수준 콜드스타트의 차이는 그대로 사용자가 부담한다. 그래서 진정한 WASM 엣지는 Fastly·Cloudflare·Fermyon Cloud·Cosmonic·Wasmer Edge로 더 자주 간다.
다만 AWS는 Bedrock의 사용자 정의 함수에서 WASM을 받아들이는 방향을 2025년 후반 발표했다. 향후 1-2년 사이 Lambda+WASM이 1급으로 올라올 가능성이 높다.
17장 · Docker WASM과 containerd-wasm-shims — 컨테이너 없는 WASM
Docker Desktop은 4.15+에서 WASM 워크로드를 정식 베타로 지원했고 2025년 GA됐다. 구현체는 containerd-shim-wasmtime, containerd-shim-wasmedge, containerd-shim-wasmer, containerd-shim-spin 네 종류다.
OCI 이미지 안에 WASM 바이너리가 있으면, 노드에서 --runtime=io.containerd.wasmedge.v1 같은 옵션 한 줄로 WASM이 실행된다. 컨테이너 런타임이 컨테이너 대신 WASM 인스턴스를 띄운다는 의미다.
Kubernetes에서는 RuntimeClass로 같은 일을 한다. 그 결과 노드 한 대에서 컨테이너와 WASM이 공존하고, 워크로드 종류에 따라 스케줄러가 자동 매칭한다.
18장 · 캐퍼빌리티 보안 모델 — 왜 WASM이 컨테이너보다 좁은 신뢰 경계인가
컨테이너의 격리는 리눅스 커널의 namespace + cgroup + seccomp + AppArmor의 조합이다. 강력하지만 커널 한 곳에 의존한다. CVE 한 건이 전체 격리를 무너뜨릴 수 있다.
WASM의 격리는 다르다.
- 메모리는 linear memory 한 덩어리. 모듈은 자신에게 할당된 영역만 본다.
- 함수 호출은 import 테이블을 통해서만. 호스트 함수를 모르면 부를 수 없다.
- 시스템콜이라는 개념 자체가 없다. WASI import를 통해서만 외부에 닿는다.
- 결정성 — 입력과 imports가 같으면 출력도 같다. 캐싱·증명·재현이 쉽다.
이 모델이 컨테이너보다 좁은 신뢰 경계를 준다. 컨테이너는 "기본은 다 줄게, 거기서 빼"의 모델이고 WASM은 "기본은 아무 것도 안 줄게, 거기서 더해"의 모델이다.
엔터프라이즈 보안 팀에게 이 차이는 매우 크다. 멀티테넌트 SaaS, 사용자 코드 실행(Cloudflare Workers, Replit, Modal), 신뢰할 수 없는 플러그인 — 이 모든 시나리오에서 WASM이 컨테이너보다 안전한 답이다.
19장 · 성능 — 콜드스타트, JIT, AOT, 그리고 pre-instantiation
WASM 성능을 한 줄로 답하긴 어렵다. 세 가지 단계를 구분하자.
- 컴파일 — .wasm 바이트코드를 네이티브 코드로 변환. JIT(Wasmtime 기본) vs AOT(WasmEdge·Wasmer LLVM·Wasmtime
--cache). - 인스턴스화 — 컴파일된 모듈에 메모리·테이블·전역을 붙여 실행 가능한 인스턴스 생성.
- 실행 — 실제 함수 호출.
콜드스타트의 비밀은 pre-instantiation과 pooling이다.
- Wasmtime의
--allow-precompiled+ .cwasm로 컴파일 단계 제로. - Pooling allocator로 인스턴스를 풀에서 재활용 → 인스턴스화 ~수십 µs.
- Fastly Compute는 모든 .wasm을 데모 안에 미리 깔아둔 채로 요청별 인스턴스만 만든다.
실행 성능은 LLVM 백엔드 기준 네이티브 대비 70-95%. SIMD·threads·tail call이 켜진 워크로드(이미지 처리, 암호화, ML 추론)는 90% 이상도 흔하다.
콜드스타트 비교(2026년 5월 기준 보고된 수치):
| 런타임 | 콜드스타트 |
|---|---|
| AWS Lambda (Node) | ~350ms |
| Cloudflare Workers (JS isolate) | ~5ms |
| Fastly Compute@Edge (WASM) | <1ms |
| Wasmtime + pooling | ~50µs |
| WasmEdge AOT | ~30µs |
20장 · 폴리글랏 데모 — Rust로 컴포넌트, JS에서 호출
이 장 하나로 컴포넌트 모델의 실용을 보자. WIT는 3장의 greeter를 그대로 쓴다.
Rust 구현(src/lib.rs):
wit_bindgen::generate!({ world: "greeter", path: "./wit" });
use exports::example::greeter::api::{Counter, Guest, GuestCounter};
use std::cell::Cell;
struct Component;
impl Guest for Component {
fn greet(name: String) -> String {
format!("Hi, {name}!")
}
type Counter = CounterImpl;
}
struct CounterImpl(Cell<u64>);
impl GuestCounter for CounterImpl {
fn new() -> Self { Self(Cell::new(0)) }
fn increment(&self) { self.0.set(self.0.get() + 1); }
fn get(&self) -> u64 { self.0.get() }
}
export!(Component);
빌드와 JS 측 호출:
cargo build --target wasm32-wasip2 --release
wasm-tools component new target/wasm32-wasip2/release/greeter.wasm -o greeter.wasm
jco transpile greeter.wasm -o out --name greeter
node -e "import('./out/greeter.js').then(m => { const c = new m.api.Counter(); c.increment(); c.increment(); console.log(m.api.greet('JS'), c.get()); })"
같은 .wasm을 Spin·wasmCloud·Wasmtime CLI에서도 그대로 부른다. 폴리글랏의 약속이 종이 위가 아니라 실행 가능한 코드 위에 있다는 점이 핵심이다.
21장 · WASM과 AI — LLM 추론과 ggml on WASM
2024년부터 본격화된 흐름이다.
- WasmEdge + llama.cpp(ggml) — Llama 3 8B를 단일 .wasm에서 추론. 1MB짜리 .wasm이 GPU/CPU 백엔드를 자동 선택한다.
- wasi-nn — WASI의 ML 인터페이스. PyTorch, ONNX, OpenVINO, TFLite를 통일된 인터페이스로 호출.
- Burn-wasm, Candle-wasm — Rust 네이티브 ML 프레임워크를 WASM으로.
- Cloudflare Workers AI + WASM 후처리 — 모델은 Workers AI가 돌리고, 응답 후처리를 WASM 컴포넌트로.
WasmEdge ggml의 매력은 모델을 OS·하드웨어 비종속으로 배포한다는 점이다. Linux x86_64, macOS arm64, Raspberry Pi, AWS Graviton에 같은 .wasm을 던지면 그 자리에서 추론을 시작한다. 임베디드와 엣지 AI의 게임 체인저다.
22장 · 라인·NHN Cloud·Cybozu — 한국·일본의 WASM 사례
한국과 일본의 도입은 인프라·콘텐츠 회사가 앞서고 있다.
- LINE/LY — 메시징 백엔드 일부 사이드카에서 WASM 플러그인을 평가 중이라는 컨퍼런스 발표(2024년 Tech-Verse).
- NHN Cloud — 자체 엣지 함수 베타에서 WasmEdge 기반 런타임을 채택. Toast 클라우드 엣지 서비스의 사용자 코드 실행 격리에 활용.
- Naver Cloud — Naver Search/Smart Store에서 사용자 정의 검색 후처리에 WASM 플러그인 평가(2025년 DAN 발표).
- Cybozu — kintone의 플러그인 모델을 Extism 기반으로 재설계하는 실험을 2024-2025년 진행.
- Sansan — 명함 데이터 처리 파이프라인 일부를 WASM 컴포넌트로 옮긴 사례를 자체 블로그에 공개.
- DeNA — 모바일 게임 클라이언트와 서버 공통 로직을 Rust→WASM으로 공유.
- NTT Communications — Smart Data Platform의 일부 노드 측 처리를 WASM으로.
이 사례들의 공통점은 컨테이너로 답이 안 나오는 멀티테넌트·플러그인·엣지 격리 문제에 WASM이 들어왔다는 점이다.
23장 · 운영 — 관측, 디버깅, 배포
WASM이 운영 수준에 오른 만큼, 관측 도구도 자리잡았다.
- wasmtime --profile=guest, --jitdump — 게스트 프로파일링. Linux perf와 통합.
- WASI Logging(wasi:logging/logging) — 구조화 로그를 호스트가 받아 OpenTelemetry로 전달.
- wasi:observe(실험적) — 트레이스/스팬을 컴포넌트 → 호스트로 흘려보내는 사양.
- Spin Trace + Fermyon Cloud Logs — Spin 워크로드의 분산 추적.
- wasmCloud + NATS Telemetry — lattice 내 호출 그래프를 NATS 메타데이터로 캡처.
디버깅은 아직 진화 중이지만, 2025년 들어 DWARF 디버그 정보를 보존한 .wasm과 wasmtime의 --gdb 모드, Chrome DevTools의 WASM 디버거가 결합되며 실무에서도 쓸 만한 수준이 됐다. AssemblyScript와 Rust는 dwarf 출력이 좋고, Go는 아직 약점이 있다.
배포는 OCI 레지스트리(ghcr.io, docker.io)에 컴포넌트 .wasm을 푸시하고 Spin/wasmCloud/Knative가 풀해가는 GitOps 흐름이 표준이다.
24장 · 미래 — wasi-preview3, async/streams, wasi-gpu, wasi-threads
2026년 중반 기준으로 가시화된 다음 스텝.
- WASI Preview 3 — async/await을 1급 ABI로 받아들이는 사양. 2026년 후반 후보 가능.
- wasi:io/streams의 일반화 — 모든 IO가 비동기 stream으로 통일.
- wasi:gpu(WebGPU on WASI) — GPU 컴퓨트를 캐퍼빌리티로. ML 추론·그래픽 가속의 결정적 사양.
- wasi-threads — 멀티스레드 컴포넌트. 현재는 Wasmtime의 실험 기능.
- 컴포넌트 ↔ Linux 프로세스 모델 — 컴포넌트가 호스트 프로세스 한 개에 1:1로 매핑되는 표준화.
- Bytecode Alliance의 산하 워킹 그룹이 안정성 레벨(Phase 4)로 끌어올리는 중.
WASM은 더 이상 단일 사양이 아니라 IETF·W3C 스타일로 인터페이스를 거버넌스하는 다층 생태계가 됐다.
25장 · 의사결정 트리 — 내 워크로드에 어떤 런타임을 골라야 하는가
마지막으로 실용 가이드.
| 워크로드 | 추천 |
|---|---|
| 엣지에서 HTTP API | Fastly Compute@Edge, Cloudflare Workers, Spin + Fermyon Cloud |
| 자체 K8s 클러스터의 사이드카 | WasmEdge + RuntimeClass, Spin + spin-operator |
| 분산 멀티 클라우드 마이크로서비스 | wasmCloud + NATS |
| AI 추론(엣지/임베디드) | WasmEdge ggml, Wasmer + Burn |
| 호스트 앱의 플러그인 | Extism |
| 동시성 중심 서비스 | Lunatic |
| 사용자 코드 실행(멀티테넌트) | Wasmtime + epoch interruption + pooling |
| Lambda 위에 얹기 | Lambda Web Adapter + Wasmtime |
선택의 4가지 축:
- 신뢰 경계 — 사용자가 코드를 가져오는가? 그렇다면 WASM.
- 콜드스타트 — ms 이하가 필요한가? 그렇다면 Fastly·Spin·WasmEdge AOT.
- 언어 다양성 — 폴리글랏인가? 그렇다면 컴포넌트 모델 1급(Wasmtime/Spin/wasmCloud).
- 운영 모델 — K8s 표준에 얹고 싶은가, PaaS에 맡기고 싶은가?
이 네 질문에 답하면 도구는 거의 자동으로 결정된다.
26장 · 마무리 — "Docker 다음"이 아니라 "Docker 위의 보안 격리"
WASM의 미래를 두고 "컨테이너를 대체할 것이냐"는 질문이 자주 나온다. 2026년의 현장 답은 단호하다 — 대체가 아니라 보완이다.
- 컨테이너는 여전히 OS 단위의 격리에 최적이다. 풀스택, OS 의존, 거대한 워크로드는 컨테이너로 간다.
- WASM은 함수·서비스 단위의 격리에 최적이다. 신뢰 없는 코드, 멀티테넌트 플러그인, 폴리글랏 ABI, 엣지가 WASM의 영역이다.
두 기술은 K8s 노드 위에 같이 산다. 워크로드 종류에 따라 RuntimeClass가 갈라준다. 솔로몬 하이크스의 트윗은 "WASM이 Docker를 대체했을 것"이 아니라 "WASM이 Docker가 풀어준 문제들 일부를 다른 방식으로 풀 수 있다" 는 더 미묘한 진실에 가깝다.
이 글은 26개 챕터로 그 다른 방식의 전모를 그렸다. WIT 한 줄을 쓰는 것에서 시작해 — 그 한 줄이 어떻게 Rust·Go·JS·Python으로 구현되고, Wasmtime·Spin·wasmCloud·Fastly·Cloudflare에서 같은 모양으로 실행되는지 — 2026년의 풍경은 그 모든 것이 동시에 가능해진 시대다.
"내 코드는 어디서 어떤 권한으로 실행되는가, 그리고 누가 그것을 조립하는가." 이 두 질문에 명확히 답할 수 있다면, 우리는 이제 그 답을 같은 .wasm 한 개로 들고 다닐 수 있다.
References
- WebAssembly 공식 — https://webassembly.org/
- WASI 공식 — https://wasi.dev/
- Component Model 명세 — https://component-model.bytecodealliance.org/
- Bytecode Alliance — https://bytecodealliance.org/
- Wasmtime 문서 — https://docs.wasmtime.dev/
- Wasmer 문서 — https://docs.wasmer.io/
- WasmEdge 문서 — https://wasmedge.org/docs/
- Fermyon Spin 문서 — https://developer.fermyon.com/spin
- wasmCloud 문서 — https://wasmcloud.com/docs
- Extism 문서 — https://extism.org/docs/overview
- JCO(JavaScript Component) — https://bytecodealliance.github.io/jco/
- wit-bindgen — https://github.com/bytecodealliance/wit-bindgen
- wasm-tools — https://github.com/bytecodealliance/wasm-tools
- Cloudflare Workers + WASM — https://developers.cloudflare.com/workers/runtime-apis/webassembly/
- Fastly Compute — https://www.fastly.com/documentation/guides/compute/
- AWS Lambda Web Adapter — https://github.com/awslabs/aws-lambda-web-adapter
- Docker WASM — https://docs.docker.com/desktop/wasm/
- Lunatic — https://lunatic.solutions/
- WASIX — https://wasix.org/
- StarlingMonkey — https://github.com/bytecodealliance/StarlingMonkey
- componentize-py — https://github.com/bytecodealliance/componentize-py
- containerd-wasm-shims — https://github.com/deislabs/containerd-wasm-shims
- Spin Operator(Kubernetes) — https://github.com/spinkube/spin-operator
- WasmEdge ggml plugin — https://github.com/second-state/WasmEdge-WASINN-examples
- Solomon Hykes tweet on WASM — https://twitter.com/solomonstre/status/1111004913222324225