Skip to content

✍️ 필사 모드: WASM 생태계 2026 — Wasmtime·Wasmer·WasmEdge·Spin·Component Model·Extism 심층 가이드 (브라우저를 넘어선 보편 실행 계층)

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

프롤로그 — 2008년의 약속, 2026년의 청구서

2017년 WebAssembly 1.0 MVP가 브라우저에 들어왔을 때, 사람들은 두 가지를 약속받았다. "브라우저에서 C/C++/Rust를 거의 네이티브 속도로 돌릴 수 있다." 그리고 "언젠가는 브라우저 바깥에서도 쓸 거다." 9년이 흘렀다. 첫 번째 약속은 Figma·AutoCAD Web·Photoshop Web으로 이미 증명되었다. 두 번째 약속은 — 솔직히 말하면 — 2024년 1월 WASI 0.2가 finalized된 이후에야 진짜로 작동하기 시작했다.

지금이 2026년 5월이다. WASM은 이미 우리가 모르게 production을 굴리고 있다. Cloudflare Workers의 일부는 V8 isolate가 아니라 Wasmtime 위에서 돌고, Shopify Functions는 가맹점이 올린 Rust/JS 코드를 WASM으로 컴파일해 엣지에서 실행한다. Fastly Compute는 처음부터 Wasmtime 기반이었다. AWS Lambda는 SnapStart에서 일부 워크로드를 WASM으로 검토하고 있고, Azure Container Apps는 SpinKube로 WASM 워크로드를 정식 지원한다. 컨테이너 다음 단계가 WASM이라는 말은 더 이상 발표 슬라이드의 약속이 아니다 — 청구서에 찍히는 호스팅 단위가 되었다.

이 글은 2026년 5월 현재 WASM 생태계의 지도를 한 번에 그린다. 런타임 4종(Wasmtime·Wasmer·WasmEdge·Spin), 표준(WASI 0.2/0.3·Component Model·WAC), 도구(Jco·Extism·wasm-tools·Wash), 언어(Wing·Kotlin/WASM·Dart/WASM), 그리고 실제 production 사례까지. 어떤 도구를 언제 쓰는지, 왜 Component Model이 큰 변화인지, 그리고 한국·일본에서는 누가 쓰고 있는지.


1장 · 2026년의 WASM — 어디까지 왔나

먼저 한 줄 요약. WASM은 브라우저 가속기에서 시작해 "보편 실행 계층"으로 자라났다. "보편 실행 계층"이라는 말이 거창하지만 실제 의미는 단순하다 — 같은 .wasm 바이너리가 브라우저·서버·엣지·임베디드·플러그인 호스트에서 모두 돈다. 그래서 한 번 만든 코드를 어디든 실행할 수 있다는 약속이 (마침내) 현실이 된 것이다.

2026년 기준 WASM의 좌표.

영역상태 (2026.05)대표 도구
브라우저 표준 WASM 1.0모든 메이저 브라우저 GAV8·SpiderMonkey·JavaScriptCore
Reference Types · SIMDGA동일
Tail Call · Multiple MemoriesGA동일
GC 제안모든 메이저 브라우저 GA (2024 후반)Kotlin/WASM·Dart/WASM 실전
Exception HandlingGAC++ 예외, Java 예외
Threads · Atomics부분 GA (cross-origin isolated 필요)rayon·OpenMP 포팅
서버 사이드 WASI 0.1안정Wasmtime 1+
서버 사이드 WASI 0.2 (Component Model)GA (2024.01)Wasmtime 17+
서버 사이드 WASI 0.3 (async)GA (2025 Q4)Wasmtime 28+
런타임 — 표준 OSS4강 + 군소Wasmtime·Wasmer·WasmEdge·Spin
패키지 레지스트리분열 (wasmer.io / OCI / wa.dev)wapm·warg·OCI
컨테이너 통합k8s에서 정식 지원containerd shim·runwasi·SpinKube
플러그인 시스템모든 언어 호스트Extism·wasmtime embed API
클라우드 네이티브 언어등장Wing·Grain·MoonBit

핵심 통찰 3개.

첫째, Component Model이 가장 큰 변화다. 2017년 WASM 1.0은 "코어 모듈"만 정의했다. 코어 모듈은 i32·i64·f32·f64·메모리·테이블만 안다. 문자열을 못 주고받는다. 그래서 호스트와 게스트가 문자열을 교환하려면 매번 "메모리 어디서부터 몇 바이트 읽어라" 같은 ABI 협상을 해야 했다. Component Model은 이 ABI를 표준으로 묶었다. 그래서 Rust로 짠 모듈을 Python·Go·JS 호스트가 별도 코드 없이 부른다. 이게 진짜로 작동하기 시작한 게 2024년 1월이다.

둘째, 런타임이 4강으로 굳어졌다. 2020년에는 10개가 넘던 WASM 런타임이 사실상 4개로 정리됐다. Bytecode Alliance의 Wasmtime(표준), Wasmer(상업+레지스트리), WasmEdge(CNCF·엣지), Spin(서버리스 플랫폼). 나머지는 임베디드 특화(WAMR·wasm3) 또는 정체 상태다.

셋째, 2026년의 WASM은 "쓰는" 단계지 "기다리는" 단계가 아니다. 2022년까지는 "언제 production-ready가 되는가"가 화두였다. 2026년은 "어떤 도구로 어떤 워크로드를 옮길지"가 화두다. 우리가 안 써도 우리 회사의 다른 팀이 쓰고 있을 확률이 높다.


2장 · WASI 0.2 Component Model (2024.01) — 왜 이것이 큰 변화인가

Component Model을 한 줄로 설명하면 — 언어 독립 함수 호출 규약(calling convention) + 인터페이스 명세(IDL) + 타입 시스템이다. gRPC가 Protobuf로 서비스 간 RPC를 표준화한 것과 비슷한 일을, WASM 모듈 간에 한 셈이다.

기존 코어 WASM의 한계부터 보자. 코어 모듈은 다음 타입만 안다.

i32, i64, f32, f64, v128, funcref, externref

문자열·구조체·옵션 타입·결과 타입(Result) — 모두 없다. 그래서 Rust 모듈이 JS 호스트에 string을 반환하려면 "메모리 주소 X에서 N바이트 UTF-8로 읽어라"라는 합의를 매번 다시 짜야 했다. wasm-bindgen이 이걸 자동화하긴 했지만 JS 한정이었다.

Component Model이 도입한 것 — 줄여서 4가지.

  1. WIT (Wasm Interface Type) — IDL. .wit 파일에 인터페이스를 선언한다. record·variant·option·result·list·string 같은 고수준 타입을 쓴다.
  2. Canonical ABI — WIT 타입이 코어 WASM의 i32·i64·메모리 레이아웃으로 어떻게 매핑되는지를 정의한 표준 ABI. 모든 언어가 같은 규약을 따른다.
  3. 컴포넌트(component) — 코어 모듈 + WIT 인터페이스 + 임포트/익스포트 명세를 묶은 단위. .wasm 파일이지만 헤더가 다르다(레이어 1 = 모듈, 레이어 2 = 컴포넌트).
  4. WASI 표준 인터페이스 — wasi:filesystem, wasi:http, wasi:cli, wasi:clocks, wasi:random, wasi:sockets, wasi:io 등이 WIT로 표준 정의됐다.

예를 들어 이런 .wit 파일.

package example:greeter@0.1.0;

interface greet {
  hello: func(name: string) -> string;
}

world greeter {
  export greet;
}

이걸 Rust로 구현하면:

wit_bindgen::generate!({
    world: "greeter",
});

struct Component;

impl exports::example::greeter::greet::Guest for Component {
    fn hello(name: String) -> String {
        format!("Hello, {}!", name)
    }
}

export!(Component);

핵심은 이 모듈을 Rust·Python·Go·JS·C# 호스트가 똑같은 방식으로 호출한다는 점이다. wasm-bindgen은 JS 호스트만 됐다. Component Model은 모든 호스트가 된다.

2026년 5월 현재 WASI 0.2 인터페이스가 정의된 영역 — wasi:filesystem(파일), wasi:http(HTTP 클라이언트/서버), wasi:cli(CLI 인자/환경변수), wasi:sockets(TCP/UDP), wasi:clocks(시계), wasi:random(난수), wasi:logging(로그), wasi:keyvalue(KV 저장소·proposal), wasi:blobstore(오브젝트 저장소·proposal). 다음 단계는 wasi:nn(머신러닝 추론)과 wasi:graphics(GPU)다.


3장 · WASI 0.3 (2025 Q4) — Async 지원 도착

WASI 0.2의 가장 큰 한계는 async가 없었다는 것이다. wasi:http 클라이언트로 외부 API를 부르려면 blocking 호출이었다. 서버를 짤 때 "한 요청 처리 중에 다른 요청 처리하기"가 안 됐다.

WASI 0.3는 이걸 해결한다. 2025년 Q4에 Wasmtime 28+ 와 wit-bindgen 0.36+ 에서 GA. 변경의 핵심은 두 가지.

  1. WIT에 async 키워드 추가. 함수 선언에 async를 붙이면 future를 반환한다.
  2. stream<T>future<T> 타입. 표준 라이브러리 수준에서 비동기 스트림을 다룬다.

예를 들어:

package example:fetcher@0.3.0;

interface fetch {
  use wasi:http/types@0.3.0.{request, response};

  async fetch: func(req: request) -> result<response, string>;
}

Rust 구현:

impl Guest for Component {
    async fn fetch(req: Request) -> Result<Response, String> {
        let client = wasi::http::outgoing_handler::handle(req).await?;
        Ok(client.into_response().await?)
    }
}

내부적으로 wit-bindgen이 future·promise polling을 캐노니컬 ABI로 변환한다. 호스트 입장에서는 컴포넌트가 일시 중지(pause)하고 다른 작업으로 양보하는 yield 포인트가 생긴 셈이다. 이게 진짜 중요한 이유는 — WASM 서버를 한 인스턴스로 멀티플렉싱할 수 있다는 것이다. 0.2까지는 "요청당 인스턴스"가 사실상 강제였다.

다만 주의점 — 2026년 5월 기준 async를 완전히 지원하는 게스트 언어는 Rust(wit-bindgen)·JS(Jco)뿐이다. Go·Python·C#는 부분 지원이고, 안정화는 2026년 후반으로 예상된다.


4장 · Wasmtime — Bytecode Alliance 표준

Wasmtime은 Bytecode Alliance(Mozilla·Fastly·Intel·Microsoft·Arm 등)가 공동 개발하는 레퍼런스 런타임이다. 2026년 5월 현재 Wasmtime 30+. 메이저 버전을 매월 한 번 끊는 정책이라(2024년 1월 17.0 → 2026년 5월 30+) 버전 번호가 빨리 올라간다.

Wasmtime의 좌표 — 한 줄 요약.

"WASI/Component Model 표준의 사실상 레퍼런스 구현. JIT(Cranelift) 컴파일러 기반. 보안과 정확성을 최우선."

핵심 특징 5개.

  1. Cranelift JIT — 자체 컴파일러 백엔드. SpiderMonkey의 Cranelift 포팅도 같은 코드베이스. AOT 컴파일(wasmtime compile)도 지원.
  2. Pulley 인터프리터 — Wasmtime 25+ 부터 도입된 자체 인터프리터. JIT를 못 쓰는 환경(예: iOS, JIT 금지 호스트)에서 fallback.
  3. WASI 0.2/0.3 first-class — Component Model 표준 구현. wit-bindgen이 만드는 Rust 코드는 Wasmtime의 Rust API에 직접 매핑된다.
  4. 호스트 임베드 API가 풍부 — Rust·C·Python·.NET 임베드. 호스트 함수를 컴포넌트에 노출하는 방식이 표준화돼 있다.
  5. 포크가 많다 — Cloudflare가 자사용으로 포크해서 일부를 V8 isolate 옆에서 쓰고, Fastly Compute는 Wasmtime 기반이다.

기본 사용 — CLI.

# 1. Rust로 컴포넌트 빌드
cargo build --target wasm32-wasip2 --release

# 2. Wasmtime으로 실행
wasmtime run --invoke 'hello("world")' \
  ./target/wasm32-wasip2/release/greeter.wasm

Rust 임베드 API.

use wasmtime::{Engine, Store, component::{Component, Linker}};

fn main() -> anyhow::Result<()> {
    let engine = Engine::default();
    let component = Component::from_file(&engine, "greeter.wasm")?;
    let linker = Linker::new(&engine);
    let mut store = Store::new(&engine, ());
    let instance = linker.instantiate(&mut store, &component)?;

    let hello = instance
        .get_typed_func::<(String,), (String,)>(&mut store, "hello")?;
    let (result,) = hello.call(&mut store, ("world".into(),))?;
    println!("{}", result);
    Ok(())
}

언제 Wasmtime을 고르나 — 거의 항상. 표준 추종이 강하고, 새 기능이 가장 먼저 들어오고, 문서가 가장 두껍다. 모르면 Wasmtime.


5장 · Wasmer — 상업 친화 런타임 + 레지스트리

Wasmer는 2018년 출범한 회사 Wasmer Inc.가 만드는 런타임이다. Bytecode Alliance에는 (한때 들어갔다 나온 뒤로) 속하지 않는다. 그래서 표준 추종보다 제품화·DX·배포에 무게가 실린다.

Wasmer의 좌표.

"실용 우선. 멀티 컴파일러 백엔드(Singlepass·Cranelift·LLVM). wasmer.io 패키지 레지스트리(=wapm 후속). Edge·Function 호스팅 서비스."

차별점 4가지.

  1. 컴파일러를 고를 수 있다. Singlepass(빠른 컴파일·느린 실행), Cranelift(균형), LLVM(느린 컴파일·빠른 실행). 서버 시작 시 LLVM, JIT 환경에서는 Singlepass 같은 식.
  2. wasmer.io 레지스트리. npm 같은 WASM 패키지 레지스트리. wasmer run wasmer/python 식으로 published 패키지를 즉시 실행. 이게 wapm의 후속이다.
  3. Wasmer Edge. 자사 서버리스/엣지 호스팅. Cloudflare Workers와 유사한 모델이지만 WASM 컴포넌트가 first-class.
  4. WASIX. Wasmer가 만든 POSIX 확장 명세. WASI 0.2 + 추가 시스템 콜(threads·fork·sockets 풀). 다만 표준이 아니라 Wasmer 전용이다 — 2026년 현재 다른 런타임에서는 안 돈다.

기본 사용.

# 패키지 레지스트리에서 즉시 실행
wasmer run wasmer/python -- -c "print('hello')"

# 로컬 .wasm 실행
wasmer run ./hello.wasm

Rust 임베드.

use wasmer::{Store, Module, Instance, imports, Function};

fn main() -> anyhow::Result<()> {
    let mut store = Store::default();
    let wat = r#"(module
        (func (export "add") (param i32 i32) (result i32)
            local.get 0
            local.get 1
            i32.add)
    )"#;
    let module = Module::new(&store, wat)?;
    let imports = imports! {};
    let instance = Instance::new(&mut store, &module, &imports)?;
    let add = instance.exports.get_typed_function::<(i32, i32), i32>(&store, "add")?;
    println!("{}", add.call(&mut store, 7, 35)?);
    Ok(())
}

언제 Wasmer를 고르나 — WASIX의 POSIX 확장이 필요할 때(예: 기존 Linux 바이너리에 가까운 환경), wasmer.io 레지스트리에서 패키지 형태로 배포하고 싶을 때, 또는 Wasmer Edge에 호스팅할 때. Component Model 추적에는 Wasmtime이 앞선다.


6장 · WasmEdge — CNCF, 엣지/IoT 특화

WasmEdge는 CNCF Sandbox(2021) → Incubating(2024)으로 올라온 런타임이다. Second State라는 회사가 주도하지만 CNCF 거버넌스 안에 있다. 좌표는 명확하다.

"엣지·IoT·서버리스에 특화. AOT 컴파일 우선. 작은 바이너리·낮은 메모리. 컨테이너 런타임 통합(runwasi·crun)."

차별점 4가지.

  1. AOT first. WasmEdge는 LLVM AOT 컴파일을 디폴트로 권장한다. 시작 시간이 짧고(콜드 스타트 ~ms), 메모리 풋프린트가 작다. Wasmtime은 JIT가 디폴트.
  2. 컨테이너 런타임 통합. Docker Desktop이 WasmEdge를 통해 docker run --runtime=io.containerd.wasmedge.v1 식으로 .wasm 컨테이너를 지원한다. crun(OCI 런타임)에도 WasmEdge 백엔드가 있다.
  3. wasi:nn 구현이 풍부. TensorFlow Lite·OpenVINO·llama.cpp 백엔드를 포함한다. 엣지에서 LLM·비전 추론을 돌리는 데 쓴다. 2026년 현재 ggml(llama.cpp) 백엔드로 7B/13B 모델을 엣지에서 돌리는 사례가 많다.
  4. 언어 SDK가 많다. Rust·Go·JS(QuickJS 임베드)·Python(pyo3-asyncio 어댑터)·C/C++. JS의 경우 QuickJS를 WASM으로 컴파일한 위에서 JS를 돌리는 식.

기본 사용.

# AOT 컴파일
wasmedge compile hello.wasm hello.aot.wasm

# 실행
wasmedge --dir .:. hello.aot.wasm

llama.cpp 백엔드로 모델 추론.

wasmedge --dir .:. \
  --nn-preload default:GGML:AUTO:llama-2-7b.Q5_K_M.gguf \
  llama-chat.wasm default

언제 WasmEdge를 고르나 — 콜드 스타트가 정말 중요한 경우(엣지 함수·IoT), Docker/k8s에 WASM 컨테이너로 통합하고 싶을 때, 또는 엣지에서 LLM/비전 추론을 돌릴 때. Component Model 추적은 다소 늦지만 코어 WASM 성능은 가장 빠른 축.


7장 · Spin (Fermyon) — 서버리스 WASM 플랫폼

Spin은 Fermyon이 2022년 발표한 서버리스 WASM 프레임워크 + CLI + 런타임이다. 2026년 현재 Spin 3.x. Wasmtime을 내부 런타임으로 쓰면서 그 위에 "함수형 서버리스" 추상화를 얹었다. Cloudflare Workers의 WASM 버전 — 이라고 보면 가깝다.

좌표.

"WASM 컴포넌트 = 함수. spin.toml로 트리거(HTTP·Redis·Cron) 선언. CLI로 빌드·실행·배포. SpinKube로 k8s 운영."

핵심 개념 — Spin App = N개 컴포넌트.

# spin.toml
spin_manifest_version = 2

[application]
name = "hello"
version = "0.1.0"

[[trigger.http]]
route = "/hello"
component = "hello-handler"

[component.hello-handler]
source = "target/wasm32-wasip2/release/hello.wasm"
allowed_outbound_hosts = ["https://api.example.com"]

Rust 핸들러:

use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;

#[http_component]
fn handle_hello(req: Request) -> anyhow::Result<impl IntoResponse> {
    Ok(Response::builder()
        .status(200)
        .header("content-type", "text/plain")
        .body("Hello from Spin!")
        .build())
}
# 로컬 실행
spin build
spin up

# Fermyon Cloud 배포
spin deploy

Spin의 차별점.

  1. 컴포넌트 모델 first. Spin 2부터 WASI 0.2 컴포넌트가 디폴트.
  2. 트리거 다양. HTTP·Cron·Redis Stream·Kafka·MQTT. 각 트리거가 별도 컴포넌트를 호출한다.
  3. 호스트 컴포넌트 풍부. wasi:keyvalue(KV·Redis·Postgres), wasi:sqlite(SQLite·Turso), wasi:llm(로컬 LLM 추론), wasi:mqtt(IoT). 게스트 코드는 표준 인터페이스만 부르고, Spin이 백엔드를 라우팅한다.
  4. SpinKube. k8s에서 Spin 앱을 CRD로 운영. kind: SpinApp를 만들면 k8s가 Wasmtime 노드 풀에서 실행. 컨테이너 없이 WASM만 굴리는 k8s 클러스터를 만들 수 있다는 뜻.

언제 Spin을 고르나 — 서버리스 함수를 WASM으로 짤 때, 멀티-트리거 워크로드(HTTP + Cron + Redis), 또는 k8s 위에서 WASM 함수 플랫폼을 굴리고 싶을 때. Cloudflare Workers의 셀프-호스트 버전이라고 봐도 무리는 없다.


8장 · Extism — 모든 언어를 위한 플러그인 시스템

Extism은 약간 다른 결의 프로젝트다. "WASM을 런타임으로 쓰지 말고, 플러그인 시스템으로 쓰자"가 한 줄 요약. Dylibso라는 회사가 만든다.

기본 아이디어 — 호스트 애플리케이션이 사용자가 작성한 코드를 안전하게 실행하려면 어떻게 하나? 옛날 답: 임베디드 Lua/JS 인터프리터. 새 답: WASM. 어떤 언어로 짜든 .wasm으로 컴파일하면 호스트가 sandbox에서 실행한다.

Extism의 차별점.

  1. 15+ 언어용 SDK. Rust·Go·Python·Node.js·Ruby·PHP·Java·Kotlin·.NET·Elixir·Zig·C++·Haskell·OCaml·Swift. 호스트 측 SDK가 가장 다양하다.
  2. PDK (Plugin Development Kit). 플러그인 개발자 측 SDK도 다양 — Rust·Go·JS·AssemblyScript·Zig·C++ 등.
  3. 표준 ABI. Extism 자체 ABI가 있고(extism_input_length·extism_alloc·extism_log_info 등), 호스트와 플러그인 사이 통신을 규격화한다.
  4. Component Model 부분 통합. 2025년부터 WASI 컴포넌트도 로드할 수 있다(완전 호환은 아니지만 대부분 동작).

호스트 측 Go SDK 예:

import "github.com/extism/go-sdk"

func main() {
    manifest := extism.Manifest{
        Wasm: []extism.Wasm{
            extism.WasmFile{Path: "count_vowels.wasm"},
        },
    }
    plugin, _ := extism.NewPlugin(ctx, manifest, extism.PluginConfig{}, nil)
    _, output, _ := plugin.Call("count_vowels", []byte("hello world"))
    fmt.Println(string(output))
}

플러그인 측 Rust PDK:

use extism_pdk::*;

#[plugin_fn]
pub fn count_vowels(input: String) -> FnResult<i64> {
    let count = input.chars().filter(|c| "aeiouAEIOU".contains(*c)).count();
    Ok(count as i64)
}

언제 Extism을 쓰나 — 자사 제품에 "사용자 코드 실행" 기능을 넣을 때. 예: SaaS의 webhook 처리·DB 트리거 함수·게임 모드 시스템·노션 같은 워크스페이스의 자동화. Component Model 표준을 100% 따르는 것보다 "당장 모든 언어 호스트에서 쓸 수 있는 플러그인 ABI"가 더 중요할 때.


9장 · Wing (Winglang) — WASM + IaC 결합 언어

Wing은 2022년 Monada가 발표한 클라우드 네이티브 프로그래밍 언어다. 2024년 1.0, 2026년 현재 2.x. 좌표가 독특하다.

"단일 언어로 애플리케이션 코드(런타임) + 인프라(컴파일타임)를 함께 표현. 컴파일러가 Terraform·CloudFormation·k8s YAML과 WASM 바이너리를 동시에 출력."

핵심 — 두 페이즈(phase) 모델. 모든 코드가 preflight(컴파일타임, 인프라) 또는 inflight(런타임, 함수 본문) 중 하나에 속한다.

bring cloud;

let bucket = new cloud.Bucket();
let queue = new cloud.Queue(timeout: 1m);

queue.setConsumer(inflight (msg: str) => {
  bucket.put("msg-{util.nanoid()}", msg);
});

이 코드를 wing compile -t tf-aws로 컴파일하면 — preflight 코드는 Terraform HCL로 변환(S3 bucket + SQS queue + Lambda function), inflight 코드는 .wasm 또는 .js로 컴파일되어 Lambda에 배포된다. -t sim을 쓰면 로컬 시뮬레이터에서 동일 코드가 돈다 — AWS 안 띄우고.

Wing이 WASM 생태계에서 흥미로운 이유 — inflight 코드 컴파일 타깃 중 하나가 .wasm(주로 Component)이다. 그래서 Wing으로 짠 함수가 SpinKube 같은 WASM 플랫폼에 바로 배포된다. 2026년 Wing 2.x에서는 wing compile -t spin-kube가 정식 지원된다.

언제 Wing을 쓰나 — 인프라와 애플리케이션을 한 언어로 묶고 싶을 때, 멀티 클라우드 추상화가 필요할 때, 또는 WASM 함수 플랫폼에 IaC 통합으로 배포할 때. CDK · Pulumi의 다음 세대를 노린다.


10장 · 브라우저 WASM — GC 제안, Kotlin/WASM, Dart/WASM

서버 사이드 이야기가 길었지만, WASM의 출발점은 브라우저였다. 2024-2026년 브라우저 WASM의 가장 큰 변화는 — GC(Garbage Collection) 제안의 메이저 브라우저 GA다.

GC 제안 이전, JVM·CLR·V8 같은 GC 언어를 WASM으로 컴파일하려면 자체 GC를 WASM 위에 구현해야 했다(Linear memory 안에 힙을 두고 mark-sweep을 도는 식). 결과는 — 메모리 사용이 2~3배, 코드 크기가 큼, 그리고 브라우저의 GC와 충돌(예: JS와 WASM heap이 따로 돌아 cross-reference 비효율).

WasmGC는 WASM 차원에서 GC 객체·struct·array를 정의한다. 그래서 컴파일러는 host GC(V8·SpiderMonkey)에 위임할 수 있다.

2026년 5월 현재 WasmGC 사용 사례.

  1. Kotlin/WASM (JetBrains) — 2024년 Beta, 2025년 Stable. Compose Multiplatform Web 타깃의 디폴트 컴파일러. Compose for Web 앱이 Kotlin/WASM으로 빌드되어 dart-native 대비 30-50% 작은 번들, 거의 네이티브 속도.
  2. Dart/WASM (Google) — 2024년 Stable. Flutter Web의 새 렌더러(impeller·CanvasKit 다음 세대)가 Dart/WASM 기반. Flutter Web 앱 시작 시간이 절반.
  3. Java/WASM (TeaVM·CheerpJ) — TeaVM이 WasmGC 백엔드를 정식 지원. 기존 Java GUI 앱(Swing 포함)을 브라우저에서 돌릴 수 있게 됐다.
  4. OCaml/WASM (Wasm_of_ocaml) — 2025년 출시. Js_of_ocaml의 후속.

비-GC 언어(Rust·C/C++·Zig)는 여전히 linear memory만 쓴다 — 자체 메모리 관리가 있는 언어이기 때문에 GC가 필요 없다.

브라우저 WASM의 다른 큰 화두 — Component Model을 브라우저에 가져올 것인가. 현재까지는 "노"다. 브라우저 WASM은 JS와 ABI를 통합하는 데 wasm-bindgen/Jco가 충분하고, Component Model은 서버 사이드 사용에 최적화돼 있다. 다만 Jco(JS 컴포넌트 런타임)가 브라우저에서도 동작하기 때문에 결국 우회 경로는 열려 있다.


11장 · 누가 실제로 WASM을 production에서 쓰나

이론은 충분하니 실제 사례를 본다. 2026년 5월 현재 확인된 production 사용 사례(공개 발표·블로그·컨퍼런스 기준).

Cloudflare Workers

V8 isolate 기반이라 알려졌지만, 2024년부터 일부 워크로드는 Wasmtime 기반 컴포넌트로 돈다. 특히 Workers AI, Durable Objects의 일부 백엔드, 그리고 Workers for Platforms의 서드파티 코드 실행. Workers Component Bindings(2025 후반 발표)는 컴포넌트 모델 컴포넌트를 Workers에 직접 배포할 수 있게 한다.

Shopify Functions

Shopify가 2022년부터 가맹점이 올린 Rust/JS 코드를 WASM으로 컴파일해서 체크아웃·할인·배송 로직을 실행한다. 백엔드는 Wasmtime. 한 요청당 ~5ms·1MB 메모리 한도. 2026년 기준 일일 10억+ 호출.

Fastly Compute

Fastly의 엣지 컴퓨트 플랫폼. 처음부터 Wasmtime 기반. 2026년 현재 Component Model이 디폴트(WASI 0.2). Fastly가 Bytecode Alliance 핵심 멤버이기도 하다.

Figma

Figma의 렌더링 코어가 C++로 짜여 WASM으로 컴파일된다. 2017년부터. Figma Desktop도 같은 WASM 모듈을 Electron 안에서 돌린다. 이게 가능한 이유 — WASM의 SIMD·Threads가 GA되면서 거의 네이티브 속도가 나왔기 때문.

Adobe (Photoshop Web·Illustrator Web)

Photoshop의 핵심 이미지 처리 엔진(C++)을 Emscripten으로 컴파일해 브라우저에서 돈다. 2021년 Photoshop Web Beta, 2023년 Illustrator Web. 풀 데스크톱 Photoshop의 30-50% 기능이 브라우저에서 동작.

AutoCAD Web

AutoDesk가 2018년부터 AutoCAD의 C++ 코어를 WASM으로 빌드. 2D/3D CAD를 브라우저에서 풀 기능으로.

Disney+, Microsoft Office for Web

Disney+ 동영상 플레이어의 일부(코덱 추가 처리)와 Office for Web의 Excel·Word 코어가 WASM으로 컴파일된 C++ 모듈에 의존.

Bloomberg Terminal Web

2024년 출시. 1990년대 C++ 기반 터미널을 WASM으로 옮겨 브라우저에서 동작.


12장 · 한국·일본의 WASM 활용 사례

해외 사례만큼 자주 다뤄지지 않지만 한국·일본에서도 production 사용이 있다. 공개된 자료 기준.

라인(LINE) — 일본·한국

라인의 일부 엣지 워크로드가 WASM 컴포넌트로 운영. 특히 채팅 메시지의 스팸·악성 콘텐츠 필터링이 Wasmtime 기반 사이드카로 돈다. 라인 엔지니어링 블로그에서 2024년 발표. 메리트는 — 룰 업데이트를 컨테이너 재배포 없이 .wasm 모듈 교체로 처리한다는 점.

토스(Toss) — 한국

토스의 일부 보안 검증 로직(클라이언트 위변조 탐지)이 WASM으로 컴파일된 Rust 모듈로 돈다. 토스페이먼츠에서도 PG 가맹점이 올린 검증 룰을 Extism 기반으로 실행. SLASH 2024 컨퍼런스에서 일부 공개.

쿠팡(Coupang) — 한국

쿠팡의 검색 랭킹 추론 일부가 WasmEdge + wasi:nn 위에서 돈다 — 정확히는 ONNX 모델을 WasmEdge에 통합한 형태. 검색 latency 안정성과 다언어 모델 통합에 유리.

ZOZO — 일본

ZOZOTOWN의 추천 시스템 A/B 테스트 인프라에서 실험적 룰을 WASM 모듈로 배포. 룰 변경을 빌드 없이 hot reload하기 위함. 2025년 ZOZO Tech Blog 공개.

Mercari — 일본

Mercari의 결제 검증 일부(특히 신원 확인 룰 엔진)가 WASM 기반. 2026년 초 Mercari Engineering Blog에 사례 공개.

CyberAgent — 일본

CyberAgent의 광고 서빙 일부 엣지 로직을 SpinKube 위에서 운영. Spin/SpinKube를 가장 적극적으로 production에 적용한 일본 사례 중 하나.

NTT 도코모·KDDI

5G MEC(Multi-access Edge Computing) 노드에서 WasmEdge를 컨테이너 대안으로 실험 중. 작은 풋프린트와 빠른 콜드스타트가 5G 엣지에 맞기 때문. 2025년 NTT Technical Review에 사례 게재.


13장 · 도구 모음 — WAC·Jco·wasm-tools·Wash

마지막으로 매일 쓰는 도구 모음.

wasm-tools

Bytecode Alliance의 만능 CLI. 모르면 일단 wasm-tools.

# 컴포넌트 헤더 확인
wasm-tools component wit greeter.wasm

# 컴포넌트 검증
wasm-tools validate --features all greeter.wasm

# WAT 디스어셈블
wasm-tools print greeter.wasm | less

# 컴포넌트 -> 어셈블된 코어 모듈
wasm-tools component unbundle greeter.wasm

WAC (WebAssembly Composition)

여러 컴포넌트를 조합해 더 큰 컴포넌트를 만드는 도구. Component Model의 진가는 컴포지션에서 나온다. WAC가 그걸 가능하게 한다.

# auth 컴포넌트 + storage 컴포넌트를 묶어 app 컴포넌트로
wac compose -d auth=./auth.wasm -d storage=./storage.wasm \
  -o app.wasm composition.wac
package example:app;

let auth = new auth:lib { ... };
let storage = new storage:lib { ... };
let app = new app:lib {
  authenticator: auth.authenticator,
  store: storage.store,
};

export app...;

Jco (JavaScript Component Toolkit)

JS와 컴포넌트 모델의 다리. 두 방향 모두 지원.

  1. .wasm 컴포넌트를 JS에서 호출 — jco transpile greeter.wasm → ES 모듈 wrapper 생성.
  2. JS 소스를 컴포넌트로 컴파일 — jco componentize greet.js -w greet.wit → .wasm 컴포넌트 생성(StarlingMonkey JS 엔진 임베드).
# Rust 컴포넌트를 JS에서 쓰기
jco transpile ./greeter.wasm -o ./out
# 그러면 out/greeter.js, out/greeter.d.ts, out/greeter.core.wasm 생성
import { hello } from './out/greeter.js'
console.log(hello('world')) // "Hello, world!"

Wash (wasmCloud Shell)

wasmCloud의 CLI/REPL. wasmCloud는 또 다른 WASM 플랫폼인데, 분산 액터(actor) 모델 위에 컴포넌트를 얹는 접근. NATS 메시지 버스 위에서 액터가 서로 통신.

# 로컬 wasmCloud 호스트 실행
wash up

# 컴포넌트(액터) 시작
wash start component ghcr.io/wasmcloud/components/http-hello-world-rust:0.1.0

# capability provider 시작 (HTTP 서버)
wash start provider ghcr.io/wasmcloud/http-server:0.20.0

언제 wasmCloud를 쓰나 — 분산 액터 모델이 맞는 워크로드(IoT·게임 서버·분산 시뮬레이션), 다수 노드에 컴포넌트를 동적으로 배포해야 할 때. Spin이 "서버리스 함수"라면 wasmCloud는 "분산 액터 메시 + 컴포넌트".


에필로그 — 2026년 우리가 WASM을 보는 법

여기까지가 2026년 5월 WASM 생태계의 지도다. 한 번에 머리에 들어오게 다시 줄이면:

  1. 표준이 굳었다. WASI 0.2(컴포넌트 모델)가 2024.01 GA, WASI 0.3(async)이 2025.Q4 GA. 이제 "기다리는 단계"는 끝났다.
  2. 런타임은 4강. Wasmtime(표준), Wasmer(상업+레지스트리), WasmEdge(엣지/IoT), Spin(서버리스 플랫폼). 모르면 Wasmtime.
  3. WASM의 가장 큰 가치는 더 이상 "빠른 브라우저 코드"가 아니다. "한 번 빌드해서 브라우저·서버·엣지·플러그인 호스트에서 다 돌리는" 보편 실행 계층이다. Component Model이 그걸 가능하게 했다.
  4. 누가 쓰나 — 대형 회사들이 이미 production에서 쓴다. Cloudflare·Shopify·Fastly·Figma·Adobe·라인·토스·쿠팡·ZOZO·Mercari·CyberAgent.
  5. 언제 쓰나 — (a) 사용자 코드를 안전하게 실행해야 할 때(Extism), (b) 엣지 함수 콜드스타트가 짧아야 할 때(Spin·WasmEdge), (c) 멀티 언어 라이브러리를 서버 사이드에서 호출해야 할 때(Wasmtime+Component Model), (d) 무거운 네이티브 로직을 브라우저에 옮길 때(Emscripten·wasm-bindgen).
  6. 언제 안 쓰나 — 평범한 마이크로서비스, 네이티브 OS API가 깊게 필요한 코드, GPU 직접 접근(아직 wasi:graphics 표준화 중), 기존 컨테이너 워크로드에 만족할 때.

마지막 한 줄. 2017년 WASM 1.0이 브라우저에 들어왔을 때 누가 9년 뒤 Cloudflare·Shopify·라인이 production을 굴리고 있을 거라고 예상했을까. 표준 하나가 GA되는 데 7년, 시장이 그 표준 위에 올라타는 데 또 2년. 이게 인프라가 굳는 속도다. 지금이 2026년이고, 우리가 안 쓰면 옆 팀이 쓴다.


참고 / References

현재 단락 (1/313)

2017년 WebAssembly 1.0 MVP가 브라우저에 들어왔을 때, 사람들은 두 가지를 약속받았다. "브라우저에서 C/C++/Rust를 거의 네이티브 속도로 돌릴 수 있다."...

작성 글자: 0원문 글자: 19,069작성 단락: 0/313