Skip to content

✍️ 필사 모드: WebAssembly 완전 가이드 2025: 브라우저를 넘어서 — WASI, Component Model, 서버사이드 Wasm

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

목차

1. WebAssembly란 무엇인가

WebAssembly(Wasm)는 스택 기반 가상 머신을 위한 바이너리 명령어 포맷이다. 원래 웹 브라우저에서 네이티브에 가까운 성능을 제공하기 위해 설계되었지만, 이제는 브라우저를 넘어 서버, 엣지, IoT까지 확장되고 있다.

1.1 Wasm의 핵심 특성

특성설명의미
바이너리 포맷컴팩트한 바이너리 인코딩빠른 전송, 빠른 디코딩
스택 머신스택 기반 명령어 실행단순하고 효율적인 실행 모델
선형 메모리연속된 바이트 배열안전한 메모리 접근, 샌드박스
타입 안전강타입 시스템컴파일 시 검증, 런타임 안전
이식성아키텍처 독립적x86, ARM, RISC-V 어디서나 실행
샌드박스격리된 실행 환경호스트 시스템 보호

1.2 Wasm의 역사

2015: WebAssembly 프로젝트 발표 (W3C)
2017: 4대 브라우저에서 Wasm 1.0 지원
2019: WASI 초기 제안 (비브라우저 Wasm)
2020: Wasm 1.0W3C 공식 권고안
2021: Component Model 제안, Fermyon 창립
2022: Docker+Wasm 기술 프리뷰, WASI Preview 1
2023: WASI 0.2 안정화, Component Model 성숙
2024: GC proposal 구현, 주요 런타임 최적화
2025: WASI 0.2 Production-ready, Wasm 서버 본격 채택

1.3 Wasm 바이너리 구조

Wasm 모듈 구조:
+------------------+
| Magic Number     |  0x00 0x61 0x73 0x6D ("\0asm")
| Version          |  0x01 0x00 0x00 0x00 (v1)
+------------------+
| Type Section     |  함수 시그니처 정의
| Import Section   |  외부 함수/메모리 임포트
| Function Section |  함수 인덱스
| Table Section    |  간접 호출 테이블
| Memory Section   |  선형 메모리 정의
| Global Section   |  전역 변수
| Export Section   |  외부 공개 함수/메모리
| Start Section    |  자동 실행 함수
| Element Section  |  테이블 초기화
| Code Section     |  함수 본문 (바이트코드)
| Data Section     |  메모리 초기 데이터
+------------------+

1.4 WAT (WebAssembly Text Format)

Wasm의 텍스트 표현 형식인 WAT를 이해하면 내부 동작을 파악할 수 있다.

;; 두 수를 더하는 간단한 Wasm 모듈
(module
  ;; 함수 타입 정의
  (type $add_type (func (param i32 i32) (result i32)))

  ;; 함수 구현
  (func $add (type $add_type) (param $a i32) (param $b i32) (result i32)
    local.get $a
    local.get $b
    i32.add
  )

  ;; 선형 메모리 (1 페이지 = 64KB)
  (memory (export "memory") 1)

  ;; 함수 내보내기
  (export "add" (func $add))
)

2. 브라우저 Wasm

2.1 다양한 언어에서 Wasm으로 컴파일

Rust - Wasm 1등 시민

// lib.rs - Rust에서 Wasm으로
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
    if n <= 1 {
        return n as u64;
    }
    let mut a: u64 = 0;
    let mut b: u64 = 1;
    for _ in 2..=n {
        let temp = a + b;
        a = b;
        b = temp;
    }
    b
}

#[wasm_bindgen]
pub struct ImageProcessor {
    width: u32,
    height: u32,
    pixels: Vec<u8>,
}

#[wasm_bindgen]
impl ImageProcessor {
    #[wasm_bindgen(constructor)]
    pub fn new(width: u32, height: u32) -> ImageProcessor {
        ImageProcessor {
            width,
            height,
            pixels: vec![0; (width * height * 4) as usize],
        }
    }

    pub fn grayscale(&mut self) {
        for chunk in self.pixels.chunks_exact_mut(4) {
            let gray = (0.299 * chunk[0] as f64
                + 0.587 * chunk[1] as f64
                + 0.114 * chunk[2] as f64) as u8;
            chunk[0] = gray;
            chunk[1] = gray;
            chunk[2] = gray;
        }
    }

    pub fn pixels_ptr(&self) -> *const u8 {
        self.pixels.as_ptr()
    }
}
# Rust -> Wasm 빌드
wasm-pack build --target web

C/C++ - Emscripten

// image_filter.c - C에서 Wasm으로
#include <emscripten.h>
#include <stdint.h>

EMSCRIPTEN_KEEPALIVE
void apply_blur(uint8_t* pixels, int width, int height) {
    uint8_t* temp = (uint8_t*)malloc(width * height * 4);

    for (int y = 1; y < height - 1; y++) {
        for (int x = 1; x < width - 1; x++) {
            for (int c = 0; c < 3; c++) {
                int sum = 0;
                for (int dy = -1; dy <= 1; dy++) {
                    for (int dx = -1; dx <= 1; dx++) {
                        sum += pixels[((y+dy)*width + (x+dx))*4 + c];
                    }
                }
                temp[(y*width + x)*4 + c] = sum / 9;
            }
            temp[(y*width + x)*4 + 3] = pixels[(y*width + x)*4 + 3];
        }
    }

    memcpy(pixels, temp, width * height * 4);
    free(temp);
}
# C -> Wasm 빌드
emcc image_filter.c -O3 -s WASM=1 \
  -s EXPORTED_FUNCTIONS='["_apply_blur"]' \
  -s EXPORTED_RUNTIME_METHODS='["cwrap"]' \
  -o image_filter.js

2.2 JavaScript와의 상호 운용

// Wasm 모듈 로드 및 사용
async function initWasm() {
  // 방법 1: fetch + instantiate
  const response = await fetch('module.wasm');
  const bytes = await response.arrayBuffer();
  const { instance } = await WebAssembly.instantiate(bytes, {
    env: {
      // 호스트 함수를 Wasm에 제공
      log_value: (value) => console.log('Wasm says:', value),
      get_time: () => Date.now(),
    }
  });

  // Wasm 함수 호출
  const result = instance.exports.add(10, 20);
  console.log('Result:', result); // 30

  // 선형 메모리 접근
  const memory = new Uint8Array(instance.exports.memory.buffer);
  // 메모리에서 데이터 읽기/쓰기

  return instance;
}

// 방법 2: wasm-bindgen (Rust)
import init, { fibonacci, ImageProcessor } from './pkg/my_wasm.js';

async function main() {
  await init();

  console.log('fib(40):', fibonacci(40));

  const processor = new ImageProcessor(800, 600);
  processor.grayscale();
}

2.3 브라우저 Wasm 주요 사용 사례

사용 사례예시성능 향상
이미지/비디오 처리Photoshop Web, FFmpeg.wasm10-50x JS 대비
게임 엔진Unity WebGL, Unreal Engine네이티브의 70-90%
코덱/압축AV1 디코딩, Brotli 압축5-20x JS 대비
암호화SHA-256, AES 연산3-10x JS 대비
CAD/3D 모델링AutoCAD Web, SketchUp네이티브 수준
과학 계산시뮬레이션, 데이터 분석10-100x JS 대비
PDF 처리pdf.js 가속, 렌더링3-5x 향상

3. WASI 0.2: 시스템 인터페이스

WASI(WebAssembly System Interface)는 Wasm이 브라우저 밖에서 파일시스템, 네트워크 등 시스템 리소스에 안전하게 접근하기 위한 표준이다.

3.1 WASI 0.2 인터페이스

WASI 0.2 구조:
+----------------------------------+
| wasi:cli        (CLI 앱 지원)    |
| wasi:http       (HTTP 클라이언트/서버) |
| wasi:filesystem (파일시스템 접근)  |
| wasi:sockets    (네트워크 소켓)   |
| wasi:clocks     (시간 관련)      |
| wasi:random     (난수 생성)      |
| wasi:io         (스트림 I/O)     |
+----------------------------------+
| Component Model (기반 레이어)     |
+----------------------------------+
| Wasm Core (실행 엔진)           |
+----------------------------------+

3.2 WASI HTTP 서버 (Rust)

// Rust + WASI HTTP 서버
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
struct TodoItem {
    id: u32,
    title: String,
    completed: bool,
}

#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
    let method = req.method().as_str();
    let path = req.path();

    match (method, path) {
        ("GET", "/api/todos") => {
            let todos = vec![
                TodoItem { id: 1, title: "Learn WASI".into(), completed: false },
                TodoItem { id: 2, title: "Build Wasm app".into(), completed: false },
            ];
            Ok(Response::builder()
                .status(200)
                .header("content-type", "application/json")
                .body(serde_json::to_string(&todos)?)
                .build())
        },
        ("POST", "/api/todos") => {
            let body: TodoItem = serde_json::from_slice(req.body())?;
            Ok(Response::builder()
                .status(201)
                .header("content-type", "application/json")
                .body(serde_json::to_string(&body)?)
                .build())
        },
        _ => Ok(Response::builder()
            .status(404)
            .body("Not Found")
            .build())
    }
}

3.3 Capability-Based 보안 모델

WASI는 Capability-Based Security를 핵심으로 한다. 프로그램은 명시적으로 부여받은 권한만 사용할 수 있다.

# WASI 실행 시 권한 부여 예시
# 특정 디렉터리만 읽기 허용
wasmtime run --dir /data::/data:readonly my-app.wasm

# 네트워크 접근 허용
wasmtime run --tcplisten 0.0.0.0:8080 my-server.wasm

# 환경 변수 전달
wasmtime run --env KEY=VALUE my-app.wasm
기존 보안 모델 (Ambient Authority):
  프로세스 -> [전체 파일시스템 접근 가능]
           -> [모든 네트워크 접근 가능]
           -> [환경 변수 모두 읽기 가능]

WASI 보안 모델 (Capability-Based):
  Wasm 모듈 -> [/data 디렉터리만 읽기 가능]
            -> [localhost:8080만 리슨 가능]
            -> [지정된 환경 변수만 접근 가능]

4. Component Model: 모듈 조합

Component Model은 Wasm 모듈을 조합하여 복잡한 애플리케이션을 구성하는 표준이다.

4.1 WIT (Wasm Interface Type)

// todo.wit - 인터페이스 정의
package example:todo@0.1.0;

interface types {
    record todo-item {
        id: u32,
        title: string,
        completed: bool,
    }

    variant todo-error {
        not-found(string),
        validation-error(string),
        storage-error(string),
    }
}

interface todo-store {
    use types.{todo-item, todo-error};

    list-todos: func() -> result<list<todo-item>, todo-error>;
    get-todo: func(id: u32) -> result<todo-item, todo-error>;
    create-todo: func(title: string) -> result<todo-item, todo-error>;
    update-todo: func(id: u32, title: string, completed: bool) -> result<todo-item, todo-error>;
    delete-todo: func(id: u32) -> result<_, todo-error>;
}

world todo-app {
    import wasi:http/outgoing-handler@0.2.0;
    import wasi:logging/logging;

    export todo-store;
}

4.2 Component 조합

# 여러 컴포넌트를 조합하여 하나의 앱 구성
# 1. 각 컴포넌트 빌드
cargo component build --release  # Rust 컴포넌트
componentize-py -d todo.wit -w todo-app app.py  # Python 컴포넌트

# 2. 컴포넌트 조합
wasm-tools compose \
  --definitions auth-component.wasm \
  --definitions db-component.wasm \
  app-component.wasm \
  -o composed-app.wasm

# 3. 조합된 컴포넌트 실행
wasmtime serve composed-app.wasm

4.3 Component Model의 장점

장점설명
언어 독립적 조합Rust 모듈 + Python 모듈 + Go 모듈을 하나로
타입 안전한 인터페이스WIT로 정의된 계약 보장
샌드박스 격리컴포넌트 간 메모리 격리
경량컨테이너 대비 수십 배 가벼움
빠른 시작마이크로초 단위 초기화
이식성어디서나 실행 가능

5. 서버사이드 Wasm 프레임워크

5.1 Fermyon Spin

Spin은 Wasm 기반 마이크로서비스를 빌드하기 위한 프레임워크다.

# spin.toml - Spin 앱 설정
spin_manifest_version = 2

[application]
name = "my-api"
version = "1.0.0"
description = "Wasm 기반 API 서버"

[[trigger.http]]
route = "/api/hello"
component = "hello"

[[trigger.http]]
route = "/api/users/..."
component = "users"

[component.hello]
source = "target/wasm32-wasi/release/hello.wasm"
allowed_outbound_hosts = []

[component.users]
source = "target/wasm32-wasi/release/users.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
key_value_stores = ["default"]
sqlite_databases = ["default"]
// Spin HTTP 핸들러 (Rust)
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use spin_sdk::key_value::Store;

#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
    // Key-Value 스토어 사용
    let store = Store::open_default()?;

    match req.method().as_str() {
        "GET" => {
            let key = req.path().trim_start_matches("/api/users/");
            match store.get(key)? {
                Some(value) => Ok(Response::builder()
                    .status(200)
                    .header("content-type", "application/json")
                    .body(value)
                    .build()),
                None => Ok(Response::builder()
                    .status(404)
                    .body("Not found")
                    .build()),
            }
        },
        "POST" => {
            let body = req.body().to_vec();
            let key = format!("user:{}", uuid::Uuid::new_v4());
            store.set(&key, &body)?;

            Ok(Response::builder()
                .status(201)
                .header("content-type", "application/json")
                .body(body)
                .build())
        },
        _ => Ok(Response::builder()
            .status(405)
            .body("Method not allowed")
            .build()),
    }
}
# Spin 앱 빌드 및 실행
spin build
spin up  # 로컬 실행 (포트 3000)

# Fermyon Cloud에 배포
spin deploy

5.2 wasmCloud

wasmCloud는 분산 Wasm 애플리케이션 플랫폼이다.

# wadm.yaml - wasmCloud 앱 매니페스트
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: my-api
  annotations:
    description: "wasmCloud HTTP API"
spec:
  components:
    - name: api-handler
      type: component
      properties:
        image: ghcr.io/myorg/api-handler:0.1.0
      traits:
        - type: spreadscaler
          properties:
            instances: 5
        - type: link
          properties:
            target: httpserver
            namespace: wasi
            package: http
            interfaces: [incoming-handler]

    - name: httpserver
      type: capability
      properties:
        image: ghcr.io/wasmcloud/http-server:0.22.0
      traits:
        - type: link
          properties:
            target: api-handler
            namespace: wasi
            package: http
            interfaces: [incoming-handler]
            source_config:
              - name: default-http
                properties:
                  address: 0.0.0.0:8080

5.3 서버사이드 Wasm 프레임워크 비교

특성Fermyon SpinwasmCloudLunatic
초점HTTP 마이크로서비스분산 애플리케이션액터 모델
배포 모델단일 노드 / 클라우드분산 격자 (lattice)클러스터
스토리지KV, SQLite, RedisCapability Provider내장
언어 지원Rust, Go, JS, PythonRust, Go, AssemblyScriptRust, AssemblyScript
콜드 스타트1ms 미만1ms 미만수 ms
성숙도GAGA초기
클라우드 서비스Fermyon CloudCosmonic없음

6. Docker + Wasm

Docker Desktop은 Wasm 컨테이너를 네이티브로 지원한다.

6.1 Docker Wasm 아키텍처

기존 Linux 컨테이너:
  Docker Engine -> containerd -> runc -> Linux Container
                                         (full OS, 수십~수백 MB)

Wasm 컨테이너:
  Docker Engine -> containerd -> runwasi -> Wasm Runtime (wasmtime/wasmedge)
                                            (Wasm 모듈,MB)

6.2 Wasm Docker 이미지 빌드

# Dockerfile.wasm - Wasm 컨테이너 이미지
FROM scratch
COPY target/wasm32-wasi/release/my-app.wasm /my-app.wasm
ENTRYPOINT ["/my-app.wasm"]
# Wasm 이미지 빌드 및 실행
docker buildx build --platform wasi/wasm -t my-wasm-app .
docker run --runtime=io.containerd.wasmtime.v1 \
  --platform wasi/wasm \
  -p 8080:8080 \
  my-wasm-app

6.3 Docker Compose with Wasm

# docker-compose.yml - Wasm + Linux 컨테이너 혼합
version: "3"

services:
  # Wasm 서비스 (초경량)
  api:
    image: my-wasm-api:latest
    runtime: io.containerd.wasmtime.v1
    platform: wasi/wasm
    ports:
      - "8080:8080"
    environment:
      - DB_HOST=postgres

  # 전통적인 Linux 컨테이너
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pgdata:/var/lib/postgresql/data

  # Wasm 워커 서비스
  worker:
    image: my-wasm-worker:latest
    runtime: io.containerd.wasmtime.v1
    platform: wasi/wasm
    environment:
      - QUEUE_URL=redis://redis:6379

  redis:
    image: redis:7-alpine

volumes:
  pgdata:

6.4 Wasm vs Linux 컨테이너 비교

특성Linux 컨테이너Wasm 컨테이너
이미지 크기50MB-1GB1-10MB
시작 시간100ms-수초1ms 미만
메모리 사용50MB-수GB1-50MB
보안 모델네임스페이스/cgroup샌드박스/Capability
이식성Linux 커널 필요아키텍처 독립
프로세스 격리OS 수준언어 수준
네트워킹완전 지원WASI 소켓 (제한적)
파일시스템완전 지원WASI FS (제한적)

7. Edge Wasm

7.1 Cloudflare Workers

// Cloudflare Worker (Wasm 기반)
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.pathname === '/api/compute') {
      // Wasm 모듈로 무거운 계산 수행
      const wasmModule = await import('./compute.wasm');
      const result = wasmModule.heavy_computation(42);

      return new Response(JSON.stringify({ result }), {
        headers: { 'Content-Type': 'application/json' }
      });
    }

    // KV 스토어 사용
    if (url.pathname.startsWith('/api/cache/')) {
      const key = url.pathname.split('/').pop();

      if (request.method === 'GET') {
        const value = await env.MY_KV.get(key);
        return new Response(value || 'Not found', {
          status: value ? 200 : 404
        });
      }

      if (request.method === 'PUT') {
        const body = await request.text();
        await env.MY_KV.put(key, body, { expirationTtl: 3600 });
        return new Response('OK');
      }
    }

    return new Response('Not found', { status: 404 });
  }
};

7.2 Fastly Compute

// Fastly Compute (Rust + Wasm)
use fastly::{Error, Request, Response};
use fastly::http::StatusCode;

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    let path = req.get_path().to_string();

    match path.as_str() {
        "/api/hello" => {
            Ok(Response::from_status(StatusCode::OK)
                .with_body_text_plain("Hello from Fastly Compute!"))
        },
        path if path.starts_with("/api/proxy/") => {
            // 백엔드로 프록시
            let backend_path = path.trim_start_matches("/api/proxy");
            let mut backend_req = req;
            backend_req.set_path(backend_path);
            backend_req.send("origin_backend")
        },
        _ => {
            Ok(Response::from_status(StatusCode::NOT_FOUND)
                .with_body_text_plain("Not found"))
        }
    }
}

7.3 Edge Wasm 플랫폼 비교

플랫폼런타임언어콜드 스타트무료 티어
Cloudflare WorkersV8 + WasmJS, Rust, C++0ms (상시 로드)10만 요청/일
Fastly ComputeWasmtimeRust, Go, JS수 ms없음
Vercel Edge FunctionsV8 + WasmJS, TS0ms (상시 로드)100만 실행/월
Deno DeployV8 + WasmJS, TS, Wasm0ms10만 요청/일
Fermyon CloudSpinRust, Go, JS, Python1ms 미만무료 베타

8. 언어별 Wasm 지원

8.1 Rust - 1등 시민

Rust는 Wasm의 가장 강력한 언어 지원을 제공한다.

// Cargo.toml
[package]
name = "my-wasm-app"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wit-bindgen = "0.25"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# 빌드 타겟
rustup target add wasm32-wasi     # WASI 타겟
rustup target add wasm32-unknown-unknown  # 브라우저 타겟

# 빌드
cargo build --target wasm32-wasi --release

# Component로 변환
wasm-tools component new target/wasm32-wasi/release/my_app.wasm \
  -o my_app.component.wasm

8.2 Go - TinyGo

// main.go - TinyGo Wasm
package main

import (
    "encoding/json"
    "net/http"

    spinhttp "github.com/fermyon/spin/sdk/go/v2/http"
)

type Response struct {
    Message string `json:"message"`
    Count   int    `json:"count"`
}

func init() {
    spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) {
        resp := Response{
            Message: "Hello from Go Wasm!",
            Count:   42,
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    })
}

func main() {}
# TinyGo로 Wasm 빌드
tinygo build -target=wasi -o main.wasm main.go

8.3 Python - componentize-py

# app.py - Python Wasm (Spin)
from spin_sdk.http import IncomingHandler, Request, Response
import json

class IncomingHandler(IncomingHandler):
    def handle_request(self, request: Request) -> Response:
        if request.method == "GET" and request.uri == "/api/hello":
            body = json.dumps({
                "message": "Hello from Python Wasm!",
                "path": request.uri,
            })
            return Response(
                200,
                {"content-type": "application/json"},
                bytes(body, "utf-8")
            )

        return Response(404, {}, b"Not found")
# Python -> Wasm 컴포넌트
componentize-py -d spin-http.wit -w spin-http-trigger app -o app.wasm

8.4 JavaScript - jco

// app.js - JavaScript Wasm Component
import { handle } from 'wasi:http/incoming-handler@0.2.0';

export const incomingHandler = {
  handle(request, responseOut) {
    const headers = new Headers();
    headers.set('Content-Type', 'application/json');

    const body = JSON.stringify({
      message: 'Hello from JS Wasm!',
      method: request.method(),
      path: request.pathWithQuery(),
    });

    const response = new OutgoingResponse(headers);
    response.setStatusCode(200);

    const bodyStream = response.body();
    bodyStream.write(new TextEncoder().encode(body));
    bodyStream.close();

    responseOut.set(response);
  }
};
# JavaScript -> Wasm Component
jco componentize app.js -w wasi-http.wit -o app.wasm

8.5 언어 지원 비교

언어Wasm 성숙도WASI 지원Component Model바이너리 크기비고
Rust매우 높음완전완전1-5MB1등 시민
C/C++높음완전부분적0.5-3MBEmscripten
Go (TinyGo)중간완전완전2-10MB표준 Go 일부 미지원
Python중간완전완전10-30MBcomponentize-py
JavaScript중간완전완전5-15MBjco
C# (.NET)중간부분적초기10-50MBNativeAOT-LLVM
Swift초기부분적초기5-20MBSwiftWasm
Kotlin초기부분적초기10-30MBKotlin/Wasm

9. 성능 비교

9.1 콜드 스타트 비교

플랫폼콜드 스타트메모리 사용비고
Wasm (Spin)0.5-1ms2-10MB마이크로초 수준
Wasm (wasmtime)1-5ms5-20MB일반적
Lambda (Python)150-300ms50-128MBVPC 추가 시 더 느림
Lambda (Java)800-3000ms128-512MBSnapStart로 개선 가능
Docker Container500-5000ms50MB-1GB이미지 크기 의존
Cloud Run300-2000ms128MB-8GB인스턴스 타입 의존

9.2 처리량 비교

HTTP "Hello World" 벤치마크 (단일 인스턴스):

Spin (Rust/Wasm):     ~150,000 req/s
Native Rust (Actix):  ~200,000 req/s
Go (net/http):        ~120,000 req/s
Node.js (Express):    ~30,000 req/s
Python (FastAPI):     ~10,000 req/s

Wasm은 네이티브의 70-90% 성능을 달성

9.3 메모리 효율성

단일 HTTP 서비스 메모리 사용:

Wasm (Spin):          2-5 MB
Wasm (wasmtime):      5-15 MB
Node.js:              30-80 MB
Python:               30-60 MB
Java (JVM):           100-300 MB
.NET:                 50-150 MB
Go:                   10-30 MB

1GB 메모리에서 동시 서비스 수:
Wasm: ~200개 서비스
Node.js: ~15개 서비스
Java: ~5개 서비스

10. 보안 모델

10.1 Wasm 샌드박스

전통적인 프로세스:
+------------------------------------------+
| 프로세스                                  |
|  - 전체 파일시스템 접근                     |
|  - 모든 네트워크 접근                       |
|  - 시스템 콜 무제한                         |
|  - 다른 프로세스 메모리 접근 (exploit 시)    |
+------------------------------------------+

Wasm 샌드박스:
+------------------------------------------+
| Wasm 모듈                                |
|  +------------------------------------+  |
|  | 선형 메모리 (모듈 전용)               |  |
|  | - 경계 검사 (bounds checking)        |  |
|  | - 호스트 메모리 접근 불가              |  |
|  +------------------------------------+  |
|  | 허가된 시스템 인터페이스만 사용         |  |
|  | - wasi:filesystem (지정 경로만)       |  |
|  | - wasi:sockets (지정 주소만)          |  |
|  +------------------------------------+  |
+------------------------------------------+

10.2 Capability-Based Security 원칙

원칙설명예시
No Ambient Authority기본 권한 없음파일시스템, 네트워크 접근 불가
Principle of Least Privilege최소 권한만 부여특정 디렉터리만 접근 허용
Explicit Capability Passing명시적 권한 전달호스트가 핸들을 전달
Revocable권한 회수 가능런타임에 권한 제거

10.3 보안 비교

보안 측면컨테이너Wasm
격리 수준OS 수준 (cgroup/namespace)언어 수준 (바이트코드 검증)
메모리 안전커널에 의존경계 검사 내장
시스템 콜seccomp으로 필터링WASI로 제한
탈출 가능성커널 취약점 시 가능매우 어려움
권한 모델유저/그룹 기반Capability 기반
코드 검증없음로드 시 검증

11. 실전 사용 사례

11.1 플러그인 시스템

// 호스트 애플리케이션 - 플러그인 로더
use wasmtime::*;
use wasmtime_wasi::WasiCtxBuilder;

fn load_plugin(plugin_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    let engine = Engine::default();
    let mut linker = Linker::new(&engine);
    wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;

    // 플러그인에 최소 권한만 부여
    let wasi = WasiCtxBuilder::new()
        .inherit_stdout()  // stdout만 허용
        // 파일시스템 접근 없음
        // 네트워크 접근 없음
        .build();

    let mut store = Store::new(&engine, wasi);
    let module = Module::from_file(&engine, plugin_path)?;
    let instance = linker.instantiate(&mut store, &module)?;

    // 플러그인 함수 호출
    let process = instance
        .get_typed_func::<(i32,), i32>(&mut store, "process")?;
    let result = process.call(&mut store, (42,))?;

    println!("Plugin result: {}", result);
    Ok(())
}

11.2 Edge Computing

Edge Wasm 아키텍처:

사용자 요청 -> [CDN Edge (300+ PoP)]
                 |
                 v
              [Wasm Worker]
                 |
                 +-> 캐시 히트: 즉시 응답 (0ms)
                 |
                 +-> 캐시 미스: 원본 서버에 요청
                 |              |
                 |              v
                 |         [Origin Server]
                 |              |
                 v              v
              [응답 + 캐시 저장]

장점:
- 사용자에게 가장 가까운 위치에서 실행
- 콜드 스타트 거의 없음
- 글로벌 분산 자동 배포

11.3 Serverless Functions

Lambda vs Wasm Serverless:

AWS Lambda:
  요청 -> API Gateway -> Lambda Runtime -> 함수 실행
  콜드 스타트: 100ms-8s
  메모리: 128MB-10GB
  과금: 1ms 단위

Wasm Serverless (Spin/Fermyon):
  요청 -> Spin Runtime -> Wasm 모듈 실행
  콜드 스타트: 0.5ms 이하
  메모리: 2-50MB
  과금: 요청 단위

11.4 블록체인 스마트 컨트랙트

여러 블록체인이 Wasm을 스마트 컨트랙트 실행 엔진으로 채택했다.

블록체인Wasm 런타임언어 지원
PolkadotSubstrateRust (ink!)
NearWasmerRust, AssemblyScript
Cosmos (CosmWasm)WasmerRust
Dfinity (ICP)커스텀Rust, Motoko

12. Wasm vs Container 비교

12.1 종합 비교

특성WasmContainer
시작 시간마이크로초-밀리초밀리초-초
이미지 크기1-50MB50MB-수GB
메모리 사용1-50MB50MB-수GB
CPU 오버헤드0-30%0-5%
보안강한 샌드박스OS 수준 격리
네트워킹WASI (제한적)완전 지원
파일시스템WASI (제한적)완전 지원
GPU 지원실험적완전 지원
에코시스템성장 중매우 성숙
디버깅발전 중성숙
상태 관리Stateless 권장Stateful 가능

12.2 언제 Wasm을 선택하나

Wasm 선택 기준:

  • 밀리초 이하 콜드 스타트 필요
  • 극한의 경량 서비스
  • 플러그인/확장 시스템
  • Edge 컴퓨팅
  • 다중 언어 모듈 조합
  • 강한 샌드박스 격리 필요
  • 제한된 리소스 환경 (IoT)

Container 선택 기준:

  • 복잡한 네트워킹
  • GPU 사용
  • 레거시 애플리케이션
  • 풍부한 에코시스템 필요
  • 상태 보존 필요
  • 대용량 메모리/스토리지

13. 미래 전망

13.1 진행 중인 Wasm 제안

제안상태설명
GC (Garbage Collection)Phase 4Java, Kotlin, Dart 등 GC 언어 지원
ThreadsPhase 3공유 메모리 멀티스레딩
SIMDPhase 4 (완료)128비트 SIMD 연산
Exception HandlingPhase 4try/catch 네이티브 지원
Stack SwitchingPhase 2코루틴, async/await 지원
Memory64Phase 364비트 메모리 주소
Branch HintingPhase 3분기 예측 힌트
Tail CallPhase 4 (완료)꼬리 호출 최적화

13.2 Wasm 미래 로드맵

2025-2026 전망:
- WASI 0.2 완전 안정화 및 주요 클라우드 채택
- Component Model 생태계 성숙
- Docker Wasm 프로덕션 레디
- GC proposal 주요 런타임 구현
- Threads proposal 안정화

2027+ 전망:
- Wasm이 컨테이너와 동등한 위상
- Edge-first 아키텍처의 기본 런타임
- IoT/임베디드 표준 실행 환경
- 다중 언어 컴포넌트 생태계 확립

14. 퀴즈

Q1. WASI의 핵심 보안 모델은 무엇인가?

정답: Capability-Based Security (권한 기반 보안)

WASI는 "No Ambient Authority" 원칙을 따른다. Wasm 모듈은 기본적으로 아무 권한도 없으며, 호스트가 명시적으로 부여한 capability(파일 핸들, 네트워크 소켓 등)만 사용할 수 있다. 이는 전통적인 Unix의 ambient authority 모델과 대비된다.

Q2. Wasm Component Model의 장점은?

정답:

  • 언어 독립적 조합: Rust, Python, Go 등 서로 다른 언어로 작성된 모듈을 하나로 조합 가능
  • WIT 인터페이스: 타입 안전한 계약으로 모듈 간 통신
  • 샌드박스 격리: 각 컴포넌트는 자신만의 메모리 공간을 가짐
  • 경량: 컨테이너 대비 수십 배 가벼움
Q3. Wasm의 콜드 스타트가 Lambda보다 빠른 이유는?

정답:

  • Wasm 바이너리는 1-10MB로 매우 작아 로딩이 빠름
  • 런타임 초기화가 마이크로초 수준 (JVM이나 Python 인터프리터 같은 무거운 초기화 없음)
  • AOT 컴파일된 바이너리 직접 실행
  • 선형 메모리 모델로 간단한 메모리 설정
  • 프로세스/컨테이너 생성 오버헤드 없음
Q4. Docker + Wasm은 어떻게 동작하는가?

정답:

Docker Desktop은 containerd의 runwasi shim을 사용하여 Wasm 컨테이너를 실행한다. 기존의 runc 대신 wasmtime이나 wasmedge 같은 Wasm 런타임이 컨테이너를 실행한다. FROM scratch 기반 이미지에 .wasm 파일만 포함하여 초경량 이미지를 만들 수 있고, docker-compose에서 Linux 컨테이너와 Wasm 컨테이너를 혼합 운용할 수 있다.

Q5. Wasm이 아직 컨테이너를 대체할 수 없는 이유는?

정답:

  • WASI의 시스템 인터페이스가 아직 제한적 (GPU, 복잡한 네트워킹 등)
  • 에코시스템이 컨테이너에 비해 미성숙
  • 레거시 애플리케이션 마이그레이션이 어려움
  • 상태 관리가 기본적으로 stateless
  • 디버깅 도구가 아직 발전 중
  • 일부 언어의 Wasm 지원이 초기 단계

단, Wasm은 컨테이너를 "대체"하기보다 "보완"하는 기술로, Edge와 경량 서비스 영역에서 컨테이너와 공존할 전망이다.


15. 참고 자료

  1. WebAssembly 공식 사이트 - https://webassembly.org/
  2. WASI 공식 문서 - https://wasi.dev/
  3. Component Model 명세 - https://component-model.bytecodealliance.org/
  4. Fermyon Spin 문서 - https://developer.fermyon.com/spin/
  5. wasmCloud 문서 - https://wasmcloud.com/docs/
  6. Bytecode Alliance - https://bytecodealliance.org/
  7. wasmtime 런타임 - https://wasmtime.dev/
  8. Docker Wasm 가이드 - https://docs.docker.com/desktop/wasm/
  9. Cloudflare Workers - https://developers.cloudflare.com/workers/
  10. Fastly Compute - https://developer.fastly.com/learning/compute/
  11. wasm-tools - https://github.com/bytecodealliance/wasm-tools
  12. WIT 명세 - https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
  13. componentize-py - https://github.com/bytecodealliance/componentize-py

현재 단락 (1/790)

WebAssembly(Wasm)는 스택 기반 가상 머신을 위한 바이너리 명령어 포맷이다. 원래 웹 브라우저에서 네이티브에 가까운 성능을 제공하기 위해 설계되었지만, 이제는 브라우저...

작성 글자: 0원문 글자: 20,756작성 단락: 0/790