C/C++ 수준의 성능을 제공하는 Rust는 WebAssembly(Wasm)의 주요 언어로 자리 잡고 있습니다. 더불어, 데이터 레이스(Data Race)를 컴파일 타임에 차단하는 Rust의 혁신적인 동시성(Concurrency) 모델을 깊게 이해해 봅니다.
Rust, delivering C/C++ level performance, is establishing itself as a premier language for WebAssembly (Wasm). Let's also dive deep into Rust's innovative Concurrency model, which prevents data races at compile time.
Rust에서 WebAssembly(Wasm)로 컴파일 Compiling Rust to WebAssembly (Wasm)
`wasm-pack` 도구와 `wasm-bindgen` 크레이트를 사용하면 Rust 코드를 자바스크립트에서 쉽게 호출할 수 있는 Wasm 모듈로 빌드할 수 있습니다.
By using the `wasm-pack` tool and `wasm-bindgen` crate, you can build Rust code into Wasm modules that can be easily invoked from JavaScript.
[package]
name = "wasm-example"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
[package]
name = "wasm-example"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
use wasm_bindgen::prelude::*;
// JS의 alert 함수를 가져와서 사용
#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}
// JS로 노출할 함수
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}! This is from Rust Wasm.", name));
}
#[wasm_bindgen]
pub fn calculate_heavy_logic(n: u32) -> u32 {
// 브라우저의 JS 스레드를 멈추게 하는 무거운 연산을 Wasm으로 이양
if n <= 1 { return n; }
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
use wasm_bindgen::prelude::*;
// Import the JS alert function
#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}
// Export a function to JS
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}! This is from Rust Wasm.", name));
}
#[wasm_bindgen]
pub fn calculate_heavy_logic(n: u32) -> u32 {
// Offload heavy computation that blocks the JS thread to Wasm
if n <= 1 { return n; }
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
JavaScript에서 호출하기 Calling from JavaScript
import { greet, calculate_heavy_logic } from './pkg/wasm_example';
greet("Frontend Developer");
const result = calculate_heavy_logic(45);
console.log(`Fib(45) from Wasm: ${result}`);
안전한 동시성 (Fearless Concurrency) Fearless Concurrency
`Arc`(Atomic Reference Counted)와 `Mutex`(Mutual Exclusion)의 조합은 Rust 멀티스레드 프로그래밍의 정석입니다. 소유권과 생명주기 검사가 컴파일 단계에서 완벽하게 동작하기 때문에, 컴파일이 성공하면 데이터 레이스(스레드 경합)가 발생하지 않음을 확신할 수 있습니다.
The combination of `Arc` (Atomic Reference Counted) and `Mutex` (Mutual Exclusion) is the standard for Rust multithreaded programming. Since ownership and lifetime checks work flawlessly at compile time, a successful compilation guarantees the absence of data races.
use std::thread;
fn main() {
// 공유 상태 생성 (Arc로 감싸서 참조 카운팅, Mutex로 내부 가변성 확보)
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
// 스레드로 이동시키기 위해 Arc 클론
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
// lock()을 얻은 동안 안전하게 데이터 변경
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
// 모든 스레드 종료 대기
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
use std::thread;
fn main() {
// Create shared state (wrapped in Arc for reference counting, and Mutex for interior mutability)
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
// Clone the Arc to move into the thread
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
// Safely mutate data while holding the lock()
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
// Wait for all threads to complete
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
✨ WebAssembly 도입의 장점 ✨ Advantages of adopting WebAssembly
- 성능: 브라우저 환경에서 이미지 처리, 비디오 인코딩, 복잡한 물리가 들어간 게임 연산 등을 네이티브에 가까운 속도로 처리합니다.
- 이식성: 한 번 작성된 Wasm 모듈은 브라우저뿐만 아니라 Node.js, Deno, Edge 워커 등 다양한 환경에서 실행됩니다.
- 보안: Wasm은 브라우저의 강력한 샌드박스 내부에서 안전하게 실행됩니다.
- Performance: Handles image processing, video encoding, and complex game physics in the browser at near-native speeds.
- Portability: Wasm modules run not only in browsers but also in Node.js, Deno, and Edge workers.
- Security: Wasm runs securely within the browser's strict sandbox.
💡 컴파일 타임에 잡히는 데이터 경합 💡 Data races caught at compile time
위의 코드에서 만약 `Arc`를 쓰지 않고 단순히 값을 스레드 안으로 빌려주려(borrow) 하거나, `Mutex`를 빼먹고 값을 변형하려 들면 Rust 컴파일러가 강력한 에러를 뱉으며 조기 차단합니다. 다른 언어에서는 런타임에 디버깅하기 매우 까다로운 버그가 Rust에선 발생조차 불가능합니다.
In the code above, if you tried to borrow a value into a thread without `Arc`, or modify the value without a `Mutex`, the Rust compiler would immediately throw a hard error. Bugs that are extremely hard to debug at runtime in other languages are literally impossible to compile in Rust.