💻 프로그래밍

WebAssembly

WebAssembly (WASM)

브라우저에서 실행되는 저수준 바이너리 포맷. 네이티브에 가까운 성능.

📖 상세 설명

WebAssembly(WASM)는 웹 브라우저에서 실행되는 저수준 바이너리 명령어 포맷입니다. C, C++, Rust 같은 고성능 언어로 작성된 코드를 웹에서 네이티브에 가까운 속도로 실행할 수 있게 해주는 혁신적인 기술입니다. JavaScript의 성능 한계를 극복하기 위해 탄생했으며, 기존 웹 기술과 함께 동작하도록 설계되었습니다.

WebAssembly는 2017년 W3C에서 공식 웹 표준으로 채택되었습니다. Mozilla, Google, Microsoft, Apple 등 주요 브라우저 벤더들이 협력하여 개발했으며, 현재 모든 주요 브라우저에서 지원됩니다. 2019년에는 W3C 공식 권고안(Recommendation)으로 승격되어 웹의 네 번째 언어(HTML, CSS, JS, WASM)로 자리매김했습니다.

WASM이 네이티브에 가까운 성능을 달성하는 이유는 바이너리 포맷의 효율성에 있습니다. 텍스트 기반인 JavaScript와 달리 WASM은 미리 컴파일된 바이너리 코드이므로 파싱과 컴파일 시간이 크게 단축됩니다. 또한 정적 타입 시스템, 선형 메모리 모델, 스택 기반 가상 머신 구조 덕분에 브라우저의 JIT 컴파일러가 고도로 최적화된 기계어 코드를 생성할 수 있습니다.

실무에서 WebAssembly는 게임 엔진(Unity, Unreal Engine), 이미지/비디오 처리(Photoshop Web, Figma), 브라우저 내 AI 추론(TensorFlow.js WASM 백엔드), 암호화 연산, CAD 애플리케이션 등 연산 집약적인 작업에 활용됩니다. 또한 WASI(WebAssembly System Interface)를 통해 서버리스 환경이나 엣지 컴퓨팅에서도 사용이 확대되고 있습니다.

💻 코드 예제

// Rust에서 WASM 모듈 작성하기
// Cargo.toml: wasm-bindgen, wasm-pack 사용

use wasm_bindgen::prelude::*;

// JavaScript에서 호출할 수 있는 함수 내보내기
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

// 문자열 처리 예제
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
    format!("안녕하세요, {}님! WASM에서 인사드립니다.", name)
}

// 이미지 처리 예제: 픽셀 밝기 조절
#[wasm_bindgen]
pub fn adjust_brightness(pixels: &mut [u8], factor: f32) {
    for pixel in pixels.iter_mut() {
        let adjusted = (*pixel as f32 * factor).min(255.0) as u8;
        *pixel = adjusted;
    }
}

// 컴파일: wasm-pack build --target web

🗣️ 실무에서 이렇게 말하세요

💬 회의에서 (성능 최적화 전략)
"이미지 필터 처리가 JavaScript로는 30fps밖에 안 나오는데, 핵심 로직을 Rust로 작성해서 WASM으로 컴파일하면 60fps까지 올릴 수 있습니다. 특히 픽셀 단위 연산은 WASM이 5~10배 빠릅니다. wasm-bindgen으로 JS 연동도 간단해요."
💬 면접에서 (WASM 장단점)
"WebAssembly의 장점은 네이티브에 가까운 성능, 다양한 언어 지원, 그리고 샌드박스 보안입니다. 단점으로는 DOM에 직접 접근할 수 없어서 JavaScript 글루 코드가 필요하고, 디버깅이 어려우며, 초기 로딩 시 WASM 파일을 다운로드해야 합니다. 그래서 모든 것을 WASM으로 만들기보다는 연산 집약적인 부분만 WASM으로 최적화하는 것이 좋습니다."
💬 기술 블로그에서
"Figma가 WASM을 도입한 이유는 명확합니다. 벡터 렌더링, 레이아웃 계산 같은 핵심 엔진을 C++로 작성하고 WASM으로 컴파일해서 브라우저에서도 데스크톱 앱 수준의 성능을 달성했습니다. 덕분에 설치 없이 브라우저에서 바로 사용할 수 있죠."
💬 코드 리뷰에서 - WASM 메모리 관리
"이 Rust WASM 함수에서 Vec을 반환하고 있는데, JavaScript 쪽에서 메모리 해제를 안 하면 누수가 발생해요. wasm-bindgen을 쓰더라도 큰 버퍼는 수동으로 free() 호출해야 합니다. 그리고 adjust_brightness 함수에서 픽셀 배열을 복사하지 말고 SharedArrayBuffer로 직접 접근하면 성능이 더 좋아요. 마지막으로 WASM 파일이 1.2MB인데, wasm-opt -O3 적용했나요? 그리고 brotli 압축하면 300KB 이하로 줄일 수 있습니다."

⚠️ 흔한 실수 & 주의사항

DOM 직접 접근 불가

WebAssembly는 DOM API에 직접 접근할 수 없습니다. UI 조작이 필요하면 JavaScript 글루 코드를 통해야 합니다. wasm-bindgen이나 Emscripten의 바인딩을 활용하세요.

디버깅 어려움

WASM 바이너리는 디버깅이 까다롭습니다. 소스맵을 생성하거나 DWARF 디버그 정보를 포함시키고, Chrome DevTools의 WASM 디버거를 활용하세요. 개발 중에는 디버그 빌드를 사용하세요.

번들 사이즈 관리

WASM 파일이 수 MB가 될 수 있습니다. wasm-opt로 최적화하고, 필요한 기능만 포함시키며, 지연 로딩을 적용하세요. gzip/brotli 압축도 필수입니다.

적절한 사용 케이스 선택

단순한 DOM 조작이나 비즈니스 로직은 JavaScript가 더 적합합니다. WASM은 이미지/비디오 처리, 게임 엔진, 암호화, 물리 시뮬레이션 등 CPU 집약적인 작업에 사용하세요.

🔗 관련 용어

📚 더 배우기