[2026] WebAssembly 완벽 가이드 | WASM·Rust·성능·브라우저·실전 활용
이 글의 핵심
WebAssembly로 고성능 웹 앱을 구축하는 완벽 가이드입니다. Rust로 WASM 빌드, JavaScript 통합, 성능 최적화까지 실전 예제로 정리했습니다.
실무 경험 공유: JavaScript 이미지 처리를 WASM으로 전환하면서, 처리 속도가 10배 빨라지고 사용자 경험이 크게 향상된 경험을 공유합니다.
들어가며: “JavaScript가 느려요”
실무 문제 시나리오
시나리오 1: 계산이 너무 느려요
JavaScript는 느립니다. WASM은 네이티브 수준입니다.
시나리오 2: 이미지 처리가 필요해요
JavaScript는 제한적입니다. WASM은 빠른 처리를 제공합니다.
시나리오 3: 게임 개발이 필요해요
성능이 중요합니다. WASM은 고성능을 제공합니다.
1. WebAssembly란?
핵심 특징
WebAssembly는 브라우저에서 실행되는 바이너리 포맷입니다. 주요 장점:
- 빠른 속도: 네이티브 수준
- 작은 크기: 압축된 바이너리
- 보안: 샌드박스 환경
- 다국어: Rust, C, C++, Go
- 브라우저 지원: 모든 모던 브라우저 성능 비교:
- JavaScript: 100ms
- WASM: 10ms
2. Rust로 WASM 빌드
설치
아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Rust 설치
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# wasm-pack 설치
cargo install wasm-pack
프로젝트 생성
cargo new --lib my-wasm-project
cd my-wasm-project
Cargo.toml
아래 코드는 toml를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
[package]
name = "my-wasm-project"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = [cdylib]
[dependencies]
wasm-bindgen = "0.2"
3. Rust 코드
기본 함수
아래 코드는 rust를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
복잡한 예제
다음은 rust를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct Calculator {
value: f64,
}
#[wasm_bindgen]
impl Calculator {
#[wasm_bindgen(constructor)]
pub fn new() -> Calculator {
Calculator { value: 0.0 }
}
pub fn add(&mut self, num: f64) {
self.value += num;
}
pub fn subtract(&mut self, num: f64) {
self.value -= num;
}
pub fn get_value(&self) -> f64 {
self.value
}
}
4. 빌드
wasm-pack build --target web
출력: 다음은 간단한 code 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
pkg/
├── my_wasm_project.js
├── my_wasm_project_bg.wasm
└── package.json
5. JavaScript 통합
기본 사용
다음은 html를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WASM Example</title>
</head>
<body>
<h1>WebAssembly Example</h1>
<div id="result"></div>
<script type="module">
import init, { add, greet } from './pkg/my_wasm_project.js';
async function run() {
await init();
const result = add(5, 3);
console.log('5 + 3 =', result);
const greeting = greet('John');
console.log(greeting);
document.getElementById('result').textContent = greeting;
}
run();
</script>
</body>
</html>
React 통합
// App.tsx
import { useEffect, useState } from 'react';
export default function App() {
const [wasm, setWasm] = useState<any>(null);
const [result, setResult] = useState<number>(0);
useEffect(() => {
async function loadWasm() {
const module = await import('./pkg/my_wasm_project.js');
await module.default();
setWasm(module);
}
loadWasm();
}, []);
const handleCalculate = () => {
if (wasm) {
const result = wasm.add(5, 3);
setResult(result);
}
};
return (
<div>
<button onClick={handleCalculate}>Calculate</button>
<p>Result: {result}</p>
</div>
);
}
6. 실전 예제: 이미지 처리
Rust
다음은 rust를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn grayscale(data: &mut [u8]) {
for i in (0..data.len()).step_by(4) {
let r = data[i] as f32;
let g = data[i + 1] as f32;
let b = data[i + 2] as f32;
let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
data[i] = gray;
data[i + 1] = gray;
data[i + 2] = gray;
}
}
JavaScript
다음은 typescript를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
import init, { grayscale } from './pkg/my_wasm_project.js';
async function processImage(imageFile: File) {
await init();
const img = new Image();
img.src = URL.createObjectURL(imageFile);
await new Promise((resolve) => {
img.onload = resolve;
});
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d')!;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
grayscale(imageData.data);
ctx.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
7. 성능 최적화
메모리 관리
다음은 rust를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct LargeData {
data: Vec<u8>,
}
#[wasm_bindgen]
impl LargeData {
#[wasm_bindgen(constructor)]
pub fn new(size: usize) -> LargeData {
LargeData {
data: vec![0; size],
}
}
pub fn process(&mut self) {
// 처리 로직
}
}
// JavaScript에서 사용 후 메모리 해제
// const data = new LargeData(1000000);
// data.process();
// data.free();
정리 및 체크리스트
핵심 요약
- WebAssembly: 브라우저 바이너리 포맷
- 빠른 속도: 네이티브 수준
- Rust: 주요 개발 언어
- JavaScript 통합: 간편한 사용
- 보안: 샌드박스 환경
- 브라우저 지원: 모든 모던 브라우저
구현 체크리스트
- Rust 설치
- wasm-pack 설치
- Rust 코드 작성
- WASM 빌드
- JavaScript 통합
- 성능 최적화
- 배포
같이 보면 좋은 글
- Rust 웹 개발 가이드
- Bun 완벽 가이드
- 성능 최적화 가이드
이 글에서 다루는 키워드
WebAssembly, WASM, Rust, Performance, Browser, Frontend, JavaScript
자주 묻는 질문 (FAQ)
Q. JavaScript를 완전히 대체할 수 있나요?
A. 아니요, 성능이 중요한 부분만 WASM으로 작성하고 나머지는 JavaScript를 사용합니다.
Q. 모든 브라우저에서 작동하나요?
A. 네, 모든 모던 브라우저(Chrome, Firefox, Safari, Edge)에서 지원합니다.
Q. Rust를 배워야 하나요?
A. WASM 개발에는 Rust가 가장 적합하지만, C/C++, Go도 가능합니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, Figma, Google Earth 등 많은 서비스에서 사용합니다.