웹어셈블리는 최신 웹 브라우저에서 실행할 수 있는 코드로 이진 명령어 형식의 저수준 언어이다.
C, C++, Rust와 같은 고성능 프로그레밍 언어로 작성된 코드를 웹에서 네이티브에 가까운 속도로 실행할 수 있게 해준다.
다음은 웹어셈블리를 사용하여 자바스크립트 alert
함수를 호출하는 예제이다.
cargo new wasm
cd wasm
wasm-bindgen와 wasm-pack을 설치한다.
cargo add wasm-bindgen
cargo install wasm-pack
Cargo.toml
파일 수정...
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.100"
cdylib
은 러스트 프로젝트를 다른 프로젝트 언어에서 호출 할 수 있는 동적 라이브러리로 컴파일할 때 사용되는 크레이트 타입이다.
main.rs
파일을 lib.rs
로 변경 한 후, 러스트 코드를 작성한다.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str); // alert 함수를 외부에서 사용할 수 있도록 선언
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name)); // alert 함수를 호출
}
wasm-pack build .
빌드 결과로 pkg
디렉토리가 생성된다.
로딩 중...
컴포넌트 파일에서 웹 어셈블리 파일을 사용하기 위해서는 변환된 js 파일을 임포트 해야 한다.
"use client";
import dynamic from "next/dynamic";
import { useEffect, useState } from "react";
function WasmAlertComponent() {
const [greet, setGreet] = useState<Function | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const loadWasm = async () => {
try {
setIsLoading(true);
setError(null);
// WASM 모듈을 동적으로 로드
const greetModule = await import("@/examples/wasm/pkg/wasm");
// greet 함수가 존재하는지 확인
if (typeof greetModule.greet === 'function') {
await greetModule.default();
setGreet(() => greetModule.greet);
} else {
throw new Error("WASM greet 함수를 찾을 수 없습니다.");
}
} catch (err) {
console.error("WASM 로딩 오류:", err);
setError(err instanceof Error ? err.message : "WASM 모듈 로딩에 실패했습니다.");
} finally {
setIsLoading(false);
}
};
loadWasm();
}, []);
const handleClick = () => {
if (greet && typeof greet === 'function') {
try {
greet("world");
} catch (err) {
console.error("WASM 함수 실행 오류:", err);
alert("WASM 함수 실행 중 오류가 발생했습니다.");
}
}
};
if (isLoading) {
return (
<div className="text-gray-500 bg-gray-100 rounded-lg p-2 flex items-center justify-center w-fit border-[1px] border-gray-300">
WASM 로딩 중...
</div>
);
}
if (error) {
return (
<div className="text-red-500 bg-red-100 rounded-lg p-2 flex items-center justify-center w-fit border-[1px] border-red-300">
오류: {error}
</div>
);
}
return (
<div
onClick={handleClick}
className="cursor-pointer text-blue-500 hover:text-blue-600 bg-blue-500/10 rounded-lg p-2
flex items-center justify-center w-fit border-[1px] border-blue-500
"
>
클릭하여 러스트 웹어셈블리 호출
</div>
);
}
const WasmAlert = dynamic(() => Promise.resolve(WasmAlertComponent), {
ssr: false,
});
export default WasmAlert;
특이하게도 문자열 처리 성능은 자바스크립트가 더 빠르다. 그 이유는 러스트에서 매 루프 반복마다 format!
매크로로 새로운 문자열을 생성하는데,
이는 내부적으로 자바스크립트와의 상호작용을 위해 문자열을 생성하는 과정에서 발생하는 오버헤드가 있기 때문이다.
또한 최신 자바스크립트 엔진은 문자열 처리와 같은 특정한 작업에서 매우 빠른 실행 속도를 보여준다.
Web Assembly는 3D 렌더링, 비디오 및 오디오 처리, 암호화 및 복잡한 수학적 계산등 cpu-intensive한 작업에서 자바스크립트보다 더 빠른 성능을 보여준다.
웹 어셈블리를 사용하여 콘웨이의 생명 게임을 작성한 예제이다.