Ver3.0 ๐ ์์ฉํ๋ก๊ทธ๋๋ฐ์์ WebAssembly ํ์ฉํ๊ธฐ: ์น์ ์ฑ๋ฅ ํ๊ณ๋ฅผ ๋ฐ์ด๋๋ ๊ธฐ์

๐ ์์ฉํ๋ก๊ทธ๋๋ฐ์์ WebAssembly ํ์ฉํ๊ธฐ: ์น์ ์ฑ๋ฅ ํ๊ณ๋ฅผ ๋ฐ์ด๋๋ ๊ธฐ์
๋ค์ดํฐ๋ธ ์์ค์ ์ฑ๋ฅ์ ์น์์ ๊ตฌํํ๋ ํ์ ์ ์ธ ๋ฐฉ๋ฒ
WebAssembly๊ฐ ๋ฌด์์ธ์ง, ์ ํ์ํ์ง๋ถํฐ ์ค์ ์์ฉํ๋ก๊ทธ๋๋ฐ์์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง๊น์ง ์น๊ตฌ์ฒ๋ผ ์ฝ๊ฒ ์๋ ค๋๋ฆด๊ฒ์! ๋ณต์กํ ๊ธฐ์ ์ฉ์ด๋ ์ต๋ํ ์ฝ๊ฒ ํ์ด์ ์ค๋ช ํ ํ ๋ ํธํ๊ฒ ์ฝ์ด์ฃผ์ธ์. ๐
๐ฏ WebAssembly, ๋๋์ฒด ๋ญ๊น?
์, ์ผ๋จ WebAssembly(์ค์ฌ์ WASM์ด๋ผ๊ณ ๋ถ๋ฅผ๊ฒ์)๊ฐ ๋ญ์ง๋ถํฐ ์์๋ณผ๊น์? ๐ค๊ฐ๋จํ๊ฒ ๋งํ๋ฉด, ์น ๋ธ๋ผ์ฐ์ ์์ ๊ฑฐ์ ๋ค์ดํฐ๋ธ ์์ค์ ์๋๋ก ์ฝ๋๋ฅผ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ๋ฐ์ด๋๋ฆฌ ํ์์ ๋ช ๋ น์ด ์งํฉ์ด์์. ๋ญ๊ฐ ์ด๋ ต๊ฒ ๋ค๋ฆฌ์ฃ ? ์ข ๋ ์ฝ๊ฒ ํ์ด๋ณผ๊ฒ์!
์ฌ๋ฌ๋ถ์ด ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ๋ ๋ณดํต JavaScript๋ฅผ ์ฌ์ฉํ์์์? JavaScript๋ ์ ๋ง ํ๋ฅญํ ์ธ์ด์ง๋ง, ๋ณต์กํ ๊ณ์ฐ์ด๋ ๋ฌด๊ฑฐ์ด ์์ ์ ํ ๋๋ ์ข ๋๋ ค์ง ์ ์์ด์. ๋ง์น ์์ ๊ฑฐ๋ก ๊ณ ์๋๋ก๋ฅผ ๋ฌ๋ฆฌ๋ ๊ฒ์ฒ๋ผ์. ๐ฒ
๊ทธ๋ฐ๋ฐ WebAssembly๋ ์ด๋ฐ ์ํฉ์์ ์คํฌ์ธ ์นด๋ฅผ ์ ๊ณตํด์ฃผ๋ ๊ฑฐ์์! ๐๏ธ C, C++, Rust ๊ฐ์ ์ธ์ด๋ก ์์ฑ๋ ์ฝ๋๋ฅผ ์น ๋ธ๋ผ์ฐ์ ์์ ์์ฒญ๋๊ฒ ๋น ๋ฅด๊ฒ ์คํํ ์ ์๊ฒ ํด์ฃผ์ฃ .
๐ ์ฑ๋ฅ ๋น๊ต: JavaScript vs WebAssembly
* ๋ณต์กํ ์ํ ์ฐ์ฐ ๊ธฐ์ค, ๋ค์ดํฐ๋ธ C++ ์ฑ๋ฅ์ 100%๋ก ๊ฐ์
* ์ค์ ์ฑ๋ฅ์ ์์
์ ํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค
๐คทโโ๏ธ ์ WebAssembly๊ฐ ํ์ํ ๊ฑธ๊น?
์ข์ ์ง๋ฌธ์ด์์! JavaScript๋ง์ผ๋ก๋ ์ถฉ๋ถํ ๋ง์ ๊ฑธ ํ ์ ์๋๋ฐ, ์ ๊ตณ์ด WebAssembly๊ฐ ํ์ํ ๊น์?๊ฒ์, ๋น๋์ค ํธ์ง, 3D ๋ ๋๋ง, ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๊ฐ์ ์์ ๋ค์ ์์ฒญ๋ ๊ณ์ฐ ๋ฅ๋ ฅ์ด ํ์ํด์. JavaScript๋ก๋ ํ ์ ์์ง๋ง, WASM์ ์ฌ์ฉํ๋ฉด 2~20๋ฐฐ ์ ๋ ๋นจ๋ผ์ง ์ ์์ด์!
ํ์ฌ์์ ์ด๋ฏธ C++๋ก ๋ง๋ค์ด์ง ํ๋ฅญํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ค๊ณ ํด๋ด์. ์ด๊ฑธ JavaScript๋ก ๋ค์ ์์ฑํ๋ ๊ฑด ์๊ฐ๋ ์ค๋ ๊ฑธ๋ฆฌ๊ณ ๋ฒ๊ทธ๋ ์๊ธธ ์ ์์ฃ . WASM์ ์ฌ์ฉํ๋ฉด ๊ธฐ์กด ์ฝ๋๋ฅผ ๊ฑฐ์ ๊ทธ๋๋ก ์น์์ ์ฌ์ฉํ ์ ์์ด์!
JavaScript๋ง ์ฌ์ฉํ ์ ์๋ ๊ฒ ์๋๋ผ, C, C++, Rust, Go ๋ฑ ์ฌ๋ฌ ์ธ์ด๋ก ์์ฑ๋ ์ฝ๋๋ฅผ ์น์์ ์คํํ ์ ์์ด์. ๊ฐ ์ธ์ด์ ์ฅ์ ์ ์น์์๋ ํ์ฉํ ์ ์๋ ๊ฑฐ์ฃ !
WASM์ ์๋๋ฐ์ค ํ๊ฒฝ์์ ์คํ๋๊ธฐ ๋๋ฌธ์ ์์ ํด์. ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ๋ ๋ณด์ฅ๋๊ณ , ๋ธ๋ผ์ฐ์ ์ ๋ณด์ ์ ์ฑ ์ ๋ฐ๋ฅด์ฃ .
๐๏ธ WebAssembly์ ๊ตฌ์กฐ์ ์๋ ์๋ฆฌ
์, ์ด์ ์ข ๋ ๊น์ด ๋ค์ด๊ฐ๋ณผ๊น์? WASM์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์์๋ด ์๋ค! ๐WebAssembly ์คํ ๊ณผ์
1์์ค ์ฝ๋ ์์ฑ
C, C++, Rust ๋ฑ์ ์ธ์ด๋ก ์ฝ๋๋ฅผ ์์ฑํด์.2์ปดํ์ผ
์์ฑํ ์ฝ๋๋ฅผ .wasm ํ์ผ(๋ฐ์ด๋๋ฆฌ ํ์)๋ก ์ปดํ์ผํด์. ์ด ๊ณผ์ ์์ Emscripten ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฃ .3๋ก๋ฉ
์น ํ์ด์ง์์ JavaScript๋ฅผ ํตํด .wasm ํ์ผ์ ๋ก๋ํด์.4์ธ์คํด์คํ
๋ธ๋ผ์ฐ์ ๊ฐ WASM ๋ชจ๋์ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ๊ณ ์คํ ์ค๋น๋ฅผ ํด์.5์คํ
JavaScript์์ WASM ํจ์๋ฅผ ํธ์ถํ๊ฑฐ๋, WASM์์ JavaScript ํจ์๋ฅผ ํธ์ถํ ์ ์์ด์!WASM์ JavaScript๋ฅผ ๋์ฒดํ๋ ๊ฒ ์๋๋ผ ๋ณด์ํ๋ ๊ฑฐ์์. ๋ ๊ธฐ์ ์ด ํจ๊ป ํ๋ ฅํด์ ๋ ๊ฐ๋ ฅํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์์ฃ !
๐ป ์ค์ ! WebAssembly ์์ํ๊ธฐ
์ด๋ก ์ ์ด์ ์ถฉ๋ถํ ์์์ผ๋, ์ค์ ๋ก ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง ๋ณผ๊น์? ๊ฐ๋จํ ์์ ๋ถํฐ ์์ํด๋ด ์๋ค! ๐์ค๋น๋ฌผ ์ฒดํฌ๋ฆฌ์คํธ โ
C/C++ ์ฝ๋๋ฅผ WASM์ผ๋ก ์ปดํ์ผํ๋ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๋๊ตฌ์์.
2. ์ต์ ๋ธ๋ผ์ฐ์
Chrome, Firefox, Safari, Edge ๋ชจ๋ WASM์ ์ง์ํด์. (2017๋ ์ดํ ๋ฒ์ )
3. ํ ์คํธ ์๋ํฐ
VS Code, Sublime Text ๋ฑ ํธํ ๊ฑธ ์ฌ์ฉํ์ธ์!
4. ๊ธฐ๋ณธ์ ์ธ C/C++ ๋๋ Rust ์ง์
์์ ์ด๋ณด์ฌ๋ ๊ด์ฐฎ์์. ์์ ๋ฅผ ๋ฐ๋ผํ๋ฉด์ ๋ฐฐ์ธ ์ ์์ด์!
๐จ ์ฒซ ๋ฒ์งธ ์์ : ๊ฐ๋จํ ๋ง์ ํจ์
C ์ธ์ด๋ก ๊ฐ๋จํ ๋ง์ ํจ์๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์:// add.c
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
return a + b;
}
emcc add.c -o add.js -s EXPORTED_FUNCTIONS='["_add"]' -s EXPORTED_RUNTIME_METHODS='["ccall","cwrap"]'
<!DOCTYPE html>
<html>
<head>
<title>WebAssembly ์์ </title>
</head>
<script>
var Module = {
onRuntimeInitialized: function() {
const add = Module.cwrap('add', 'number', ['number', 'number']);
console.log('5 + 3 = ' + add(5, 3)); // 8 ์ถ๋ ฅ!
}
};
</script>
<script src="add.js"></script>
</html>
๋ฐฉ๊ธ ์ฒซ WebAssembly ํ๋ก๊ทธ๋จ์ ๋ง๋ค์์ด์! ๊ฐ๋จํ์ฃ ? ์ด์ ๋ ๋ณต์กํ ๊ฒ๋ค์ ๋ง๋ค์ด๋ณผ ์ ์์ด์!
๐ฎ ์ค์ ํ์ฉ ์ฌ๋ก๋ค
์ด๋ก ๊ณผ ๊ฐ๋จํ ์์ ๋ ๋ดค์ผ๋, ์ค์ ๋ก ์ด๋์ ์ฌ์ฉ๋๋์ง ๋ณผ๊น์? ์ ๋ง ๋ค์ํ ๊ณณ์์ ํ์ฉ๋๊ณ ์์ด์!๐ฎ ๊ฒ์ ๊ฐ๋ฐ
Unity, Unreal Engine๋ํ ๊ฒ์ ์์ง๋ค์ด WASM์ ์ง์ํด์. ๋ธ๋ผ์ฐ์ ์์ ๊ณ ํ์ง 3D ๊ฒ์์ ํ๋ ์ดํ ์ ์์ฃ !
์์: Google Stadia, Epic Games์ ์น ๋ฐ๋ชจ
๐จ ์ด๋ฏธ์ง/๋น๋์ค ์ฒ๋ฆฌ
Adobe, FigmaPhotoshop ์น ๋ฒ์ ์ด๋ Figma ๊ฐ์ ๋์์ธ ํด๋ค์ด WASM์ ํ์ฉํด์ ๋น ๋ฅธ ๋ ๋๋ง์ ๊ตฌํํด์!
์ฑ๋ฅ: JavaScript ๋๋น 3-5๋ฐฐ ๋น ๋ฆ
๐ฌ ๊ณผํ ๊ณ์ฐ
๋ฐ์ดํฐ ๋ถ์, ์๋ฎฌ๋ ์ด์ ๋ณต์กํ ์ํ ์ฐ์ฐ์ด๋ ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ ์ ๋ธ๋ผ์ฐ์ ์์ ์คํํ ์ ์์ด์.
์์: TensorFlow.js, OpenCV.js
๐ต ์ค๋์ค ์ฒ๋ฆฌ
์์ ์ ์, ์ค์๊ฐ ์ฒ๋ฆฌDAW(Digital Audio Workstation)๋ฅผ ์น์์ ๊ตฌํํ๊ฑฐ๋, ์ค์๊ฐ ์ค๋์ค ์ดํํธ๋ฅผ ์ ์ฉํ ์ ์์ด์!
์์: Soundtrap, BandLab
๐ฐ ์ํธํํ
๋ธ๋ก์ฒด์ธ, ์ง๊ฐ์ํธํ ์ฐ์ฐ์ด ๋ง์ด ํ์ํ ๋ธ๋ก์ฒด์ธ ์ ํ๋ฆฌ์ผ์ด์ ์์ WASM์ ํ์ฉํด์.
์์: Polkadot, NEAR Protocol
๐ ๋ฐ์ดํฐ ์๊ฐํ
๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์๋ฐฑ๋ง ๊ฐ์ ๋ฐ์ดํฐ ํฌ์ธํธ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ ๋๋งํ๊ณ ์ํธ์์ฉํ ์ ์์ด์!
์์: Tableau, Observable
๐ ๏ธ ์์ฉํ๋ก๊ทธ๋๋ฐ์์์ ์ค์ ํ์ฉ๋ฒ
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์์ฉํ๋ก๊ทธ๋๋ฐ์์ WASM์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์์๋ด ์๋ค! ์ค๋ฌด์์ ๋ฐ๋ก ์ธ ์ ์๋ ํ๋ค์ด์์. ๐ผ1๏ธโฃ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ์ ํ๋ฆฌ์ผ์ด์ ๋ง๋ค๊ธฐ
์ฌ์ง ํธ์ง ์ฑ์ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํด๋ณผ๊ฒ์. ํํฐ ์ ์ฉ, ํฌ๊ธฐ ์กฐ์ , ํฌ๋งท ๋ณํ ๋ฑ์ ์์ ์ด ํ์ํ์ฃ .// image_processor.c
#include <emscripten.h>
#include <stdlib.h>
EMSCRIPTEN_KEEPALIVE
void applyGrayscale(unsigned char* imageData, int width, int height) {
for(int i = 0; i < width * height * 4; i += 4) {
unsigned char r = imageData[i];
unsigned char g = imageData[i + 1];
unsigned char b = imageData[i + 2];
// ๊ทธ๋ ์ด์ค์ผ์ผ ๋ณํ ๊ณต์
unsigned char gray = (r * 0.299 + g * 0.587 + b * 0.114);
imageData[i] = gray;
imageData[i + 1] = gray;
imageData[i + 2] = gray;
}
}
async function processImage(imageElement) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = imageElement.width;
canvas.height = imageElement.height;
ctx.drawImage(imageElement, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// WASM ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ฏธ์ง ๋ฐ์ดํฐ ๋ณต์ฌ
const dataPtr = Module._malloc(data.length);
Module.HEAPU8.set(data, dataPtr);
// WASM ํจ์ ํธ์ถ
Module._applyGrayscale(dataPtr, canvas.width, canvas.height);
// ๊ฒฐ๊ณผ ๊ฐ์ ธ์ค๊ธฐ
const resultData = Module.HEAPU8.subarray(dataPtr, dataPtr + data.length);
imageData.data.set(resultData);
ctx.putImageData(imageData, 0, 0);
Module._free(dataPtr);
return canvas.toDataURL();
}
์ด ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ฉด JavaScript๋ง ์ฌ์ฉํ ๋๋ณด๋ค 5-10๋ฐฐ ๋น ๋ฅธ ์ด๋ฏธ์ง ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํด์! ํนํ ๊ณ ํด์๋ ์ด๋ฏธ์ง๋ ์ค์๊ฐ ๋น๋์ค ์ฒ๋ฆฌ์ ํจ๊ณผ์ ์ด์ฃ .
2๏ธโฃ ๊ฒ์ ๋ฌผ๋ฆฌ ์์ง ๊ตฌํํ๊ธฐ
๊ฒ์์์ ์ถฉ๋ ๊ฐ์ง๋ ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ ์ ๊ณ์ฐ์ด ๋ง์ด ํ์ํ ์์ ์ด์์. WASM์ผ๋ก ๊ตฌํํ๋ฉด ํจ์ฌ ๋ถ๋๋ฌ์ด ๊ฒ์ํ๋ ์ด๋ฅผ ๋ง๋ค ์ ์์ด์!// physics.cpp
#include <emscripten/bind.h>
#include <cmath>
class PhysicsObject {
public:
float x, y;
float vx, vy;
float mass;
PhysicsObject(float x, float y, float mass)
: x(x), y(y), vx(0), vy(0), mass(mass) {}
void update(float dt, float gravity) {
vy += gravity * dt;
x += vx * dt;
y += vy * dt;
}
bool checkCollision(PhysicsObject& other) {
float dx = x - other.x;
float dy = y - other.y;
float distance = std::sqrt(dx * dx + dy * dy);
return distance < 20.0f; // ๋ฐ์ง๋ฆ 20 ๊ฐ์
}
void resolveCollision(PhysicsObject& other) {
// ๊ฐ๋จํ ํ์ฑ ์ถฉ๋ ๊ตฌํ
float dx = other.x - x;
float dy = other.y - y;
float distance = std::sqrt(dx * dx + dy * dy);
if(distance == 0) return;
float nx = dx / distance;
float ny = dy / distance;
float dvx = other.vx - vx;
float dvy = other.vy - vy;
float dvn = dvx * nx + dvy * ny;
if(dvn > 0) return;
float impulse = 2 * dvn / (mass + other.mass);
vx += impulse * other.mass * nx;
vy += impulse * other.mass * ny;
other.vx -= impulse * mass * nx;
other.vy -= impulse * mass * ny;
}
};
EMSCRIPTEN_BINDINGS(physics_module) {
emscripten::class_<PhysicsObject>("PhysicsObject")
.constructor<float, float, float>()
.property("x", &PhysicsObject::x)
.property("y", &PhysicsObject::y)
.property("vx", &PhysicsObject::vx)
.property("vy", &PhysicsObject::vy)
.function("update", &PhysicsObject::update)
.function("checkCollision", &PhysicsObject::checkCollision)
.function("resolveCollision", &PhysicsObject::resolveCollision);
}
// ๊ฒ์ ๋ฃจํ
const objects = [
new Module.PhysicsObject(100, 100, 1.0),
new Module.PhysicsObject(200, 150, 1.5),
new Module.PhysicsObject(300, 200, 2.0)
];
function gameLoop(timestamp) {
const dt = 0.016; // 60 FPS
const gravity = 9.8;
// ๋ฌผ๋ฆฌ ์
๋ฐ์ดํธ
objects.forEach(obj => obj.update(dt, gravity));
// ์ถฉ๋ ๊ฐ์ง ๋ฐ ์ฒ๋ฆฌ
for(let i = 0; i < objects.length; i++) {
for(let j = i + 1; j < objects.length; j++) {
if(objects[i].checkCollision(objects[j])) {
objects[i].resolveCollision(objects[j]);
}
}
}
// ๋ ๋๋ง
render(objects);
requestAnimationFrame(gameLoop);
}
gameLoop();
3๏ธโฃ ๋ฐ์ดํฐ ์์ถ/์ํธํ ์์คํ
๋ณด์์ด ์ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ์์ WASM์ ํ์ฉํ ์ ์์ด์. ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ๋ณต์กํ ์ฐ์ฐ์ด ๋ง์์ WASM์ด ํนํ ์ ์ฉํ์ฃ !// crypto.c
#include <emscripten.h>
#include <string.h>
EMSCRIPTEN_KEEPALIVE
void xorEncrypt(unsigned char* data, int length, unsigned char* key, int keyLength) {
for(int i = 0; i < length; i++) {
data[i] ^= key[i % keyLength];
}
}
EMSCRIPTEN_KEEPALIVE
unsigned char* compress(unsigned char* data, int length, int* outLength) {
// ๊ฐ๋จํ RLE (Run-Length Encoding) ์์ถ
unsigned char* compressed = (unsigned char*)malloc(length * 2);
int writePos = 0;
for(int i = 0; i < length; ) {
unsigned char current = data[i];
int count = 1;
while(i + count < length && data[i + count] == current && count < 255) {
count++;
}
compressed[writePos++] = count;
compressed[writePos++] = current;
i += count;
}
*outLength = writePos;
return compressed;
}
๐ฏ Rust๋ก WebAssembly ๋ง๋ค๊ธฐ
C/C++๋ ์ข์ง๋ง, ์์ฆ์ Rust๋ก WASM์ ๋ง๋๋ ๊ฒ ์ธ๊ธฐ์์! Rust๋ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ์ด ๋ณด์ฅ๋๊ณ , ํ๋์ ์ธ ์ธ์ด ๊ธฐ๋ฅ๋ค์ด ๋ง์์ ๊ฐ๋ฐํ๊ธฐ ํธํด์. ๐ฆRust + WASM ์์ํ๊ธฐ
๋จผ์ wasm-pack์ ์ค์นํด์:curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
cargo new --lib my-wasm-project
cd my-wasm-project
[package]
name = "my-wasm-project"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
[dependencies.web-sys]
version = "0.3"
features = ["console"]
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
let message = format!("์๋
ํ์ธ์, {}๋! ๐", name);
log(&message);
message
}
#[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) -> f64 {
self.value += num;
self.value
}
pub fn subtract(&mut self, num: f64) -> f64 {
self.value -= num;
self.value
}
pub fn multiply(&mut self, num: f64) -> f64 {
self.value *= num;
self.value
}
pub fn divide(&mut self, num: f64) -> Result<f64, JsValue> {
if num == 0.0 {
return Err(JsValue::from_str("0์ผ๋ก ๋๋ ์ ์์ต๋๋ค!"));
}
self.value /= num;
Ok(self.value)
}
pub fn get_value(&self) -> f64 {
self.value
}
pub fn reset(&mut self) {
self.value = 0.0;
}
}
wasm-pack build --target web
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Rust WASM ๊ณ์ฐ๊ธฐ</title>
</head>
<script type="module">
import init, { greet, Calculator } from './pkg/my_wasm_project.js';
async function run() {
await init();
// ์ธ์ฌ ํจ์ ํ
์คํธ
const greeting = greet("์ฌ๋ฅ๋ท ์ฌ์ฉ์");
console.log(greeting);
// ๊ณ์ฐ๊ธฐ ์ฌ์ฉ
const calc = new Calculator();
console.log("10 ๋ํ๊ธฐ:", calc.add(10));
console.log("5 ๊ณฑํ๊ธฐ:", calc.multiply(5));
console.log("2๋ก ๋๋๊ธฐ:", calc.divide(2));
console.log("ํ์ฌ ๊ฐ:", calc.get_value());
}
run();
</script>
</html>
Rust๋ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ์ด ์ปดํ์ผ ํ์์ ๋ณด์ฅ๋๊ธฐ ๋๋ฌธ์, ๋ฐํ์ ์๋ฌ๊ฐ ํจ์ฌ ์ ์ด์. ๋ํ wasm-bindgen ๋๋ถ์ JavaScript์์ ์ํธ์์ฉ์ด ๋งค์ฐ ํธ๋ฆฌํ์ฃ !
โก ์ฑ๋ฅ ์ต์ ํ ํ
WASM์ ์ฌ์ฉํ๋ค๊ณ ํด์ ๋ฌด์กฐ๊ฑด ๋น ๋ฅธ ๊ฑด ์๋์์. ์ ๋๋ก ์ต์ ํํด์ผ ์ง์ง ์ฑ๋ฅ์ ๋์ด๋ผ ์ ์์ฃ ! ์ฌ๊ธฐ ์ค์ ํ๋ค์ ์๋ ค๋๋ฆด๊ฒ์. ๐1. ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ต์ ํ
โ ๋์ ์์:// JavaScript์์ ๋งค๋ฒ ๋ฉ๋ชจ๋ฆฌ ํ ๋น/ํด์
function processData(data) {
const ptr = Module._malloc(data.length);
Module.HEAPU8.set(data, ptr);
Module._process(ptr, data.length);
const result = Module.HEAPU8.subarray(ptr, ptr + data.length);
Module._free(ptr);
return result;
}
// ๋ฉ๋ชจ๋ฆฌ ํ ์ฌ์ฉ
class WasmMemoryPool {
constructor(size) {
this.ptr = Module._malloc(size);
this.size = size;
}
processData(data) {
if(data.length > this.size) {
throw new Error("๋ฐ์ดํฐ๊ฐ ๋๋ฌด ํฝ๋๋ค!");
}
Module.HEAPU8.set(data, this.ptr);
Module._process(this.ptr, data.length);
return Module.HEAPU8.subarray(this.ptr, this.ptr + data.length);
}
destroy() {
Module._free(this.ptr);
}
}
const pool = new WasmMemoryPool(1024 * 1024); // 1MB ํ
2. ๋ฐ์ดํฐ ์ ์ก ์ต์ํ
JavaScript์ WASM ์ฌ์ด์ ๋ฐ์ดํฐ ์ ์ก์ ๋น์ฉ์ด ๋ค์ด์. ๊ฐ๋ฅํ๋ฉด ์ต์ํํ์ธ์!โ ๋์ ์์:
// ๋งค ํ๋ ์๋ง๋ค ๋ฐ์ดํฐ ์ ์ก
function gameLoop() {
for(let obj of objects) {
const result = Module._updateObject(obj.x, obj.y, obj.vx, obj.vy);
obj.x = result.x;
obj.y = result.y;
}
}
// ๋ฐฐ์น ์ฒ๋ฆฌ
function gameLoop() {
// ๋ชจ๋ ๊ฐ์ฒด ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์ ์ก
const dataArray = new Float32Array(objects.length * 4);
objects.forEach((obj, i) => {
dataArray[i * 4] = obj.x;
dataArray[i * 4 + 1] = obj.y;
dataArray[i * 4 + 2] = obj.vx;
dataArray[i * 4 + 3] = obj.vy;
});
Module._updateAllObjects(dataArray.byteOffset, objects.length);
// ๊ฒฐ๊ณผ ํ ๋ฒ์ ๊ฐ์ ธ์ค๊ธฐ
objects.forEach((obj, i) => {
obj.x = dataArray[i * 4];
obj.y = dataArray[i * 4 + 1];
});
}
3. SIMD ํ์ฉํ๊ธฐ
SIMD(Single Instruction Multiple Data)๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฒกํฐ ์ฐ์ฐ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ ์ ์์ด์!// C ์ฝ๋์์ SIMD ์ฌ์ฉ
#include <wasm_simd128.h>
void vectorAdd(float* a, float* b, float* result, int length) {
int i = 0;
// 4๊ฐ์ฉ ์ฒ๋ฆฌ
for(; i <= length - 4; i += 4) {
v128_t va = wasm_v128_load(&a[i]);
v128_t vb = wasm_v128_load(&b[i]);
v128_t vr = wasm_f32x4_add(va, vb);
wasm_v128_store(&result[i], vr);
}
// ๋๋จธ์ง ์ฒ๋ฆฌ
for(; i < length; i++) {
result[i] = a[i] + b[i];
}
}
emcc -msimd128 vector.c -o vector.js
4. ์ปดํ์ผ ์ต์ ํ ์ต์
| ์ต์ | ์ค๋ช | ์ฌ์ฉ ์๊ธฐ |
|---|---|---|
-O0 |
์ต์ ํ ์์ | ๋๋ฒ๊น ์ |
-O1 |
๊ธฐ๋ณธ ์ต์ ํ | ๊ฐ๋ฐ ์ค |
-O2 |
์ค๊ฐ ์ต์ ํ | ํ ์คํธ ์ |
-O3 |
์ต๋ ์ต์ ํ | ํ๋ก๋์ |
-Os |
ํฌ๊ธฐ ์ต์ ํ | ํ์ผ ํฌ๊ธฐ ์ค์ํ ๋ |
-Oz |
์ต๋ ํฌ๊ธฐ ์ต์ ํ | ๋ชจ๋ฐ์ผ ํ๊ฒฝ |
emcc -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 -s EXPORT_ES6=1 \
--closure 1 \
mycode.c -o mycode.js
๐ง ๋๋ฒ๊น ๊ณผ ํ๋กํ์ผ๋ง
WASM ์ฝ๋๋ฅผ ๋๋ฒ๊น ํ๋ ๊ฑด ์ฒ์์ ์ข ์ด๋ ค์ธ ์ ์์ด์. ํ์ง๋ง ์์ฆ์ ๋๊ตฌ๋ค์ด ๋ง์ด ์ข์์ก๋ต๋๋ค! ๐ ๏ธChrome DevTools ํ์ฉํ๊ธฐ
์ปดํ์ผ ์ ์์ค๋งต์ ์์ฑํ๋ฉด ์๋ณธ C/C++ ์ฝ๋๋ฅผ ๋ณผ ์ ์์ด์:
emcc -g4 --source-map-base http://localhost:8000/ mycode.c -o mycode.js
Chrome DevTools์์ WASM ์ฝ๋์ ์ง์ ๋ธ๋ ์ดํฌํฌ์ธํธ๋ฅผ ์ค์ ํ ์ ์์ด์!
3. ๋ฉ๋ชจ๋ฆฌ ๊ฒ์ฌ
Memory ํญ์์ WASM ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์๊ฐ์ผ๋ก ๋ชจ๋ํฐ๋งํ ์ ์์ด์.
์ฑ๋ฅ ํ๋กํ์ผ๋ง
// JavaScript์์ ์ฑ๋ฅ ์ธก์
console.time('WASM ์คํ');
Module._myFunction(data);
console.timeEnd('WASM ์คํ');
// ๋ ์ ํํ ์ธก์
const start = performance.now();
Module._myFunction(data);
const end = performance.now();
console.log(`์คํ ์๊ฐ: ${end - start}ms`);
Chrome DevTools์ Performance ํญ์ ์ฌ์ฉํ๋ฉด JavaScript์ WASM ์คํ ์๊ฐ์ ์๊ฐ์ ์ผ๋ก ๋น๊ตํ ์ ์์ด์. ๋ณ๋ชฉ ์ง์ ์ ์ฐพ๋ ๋ฐ ์์ฃผ ์ ์ฉํ์ฃ !
๐ ์ค์ ํ๋ก์ ํธ: ์ด๋ฏธ์ง ํํฐ ์น์ฑ ๋ง๋ค๊ธฐ
์ด์ ๋ฐฐ์ด ๊ฑธ ์ข ํฉํด์ ์ค์ ๋ก ๋์ํ๋ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์? Instagram ์คํ์ผ์ ์ด๋ฏธ์ง ํํฐ ์ฑ์ ๋ง๋ค์ด๋ด ์๋ค! ๐ธํ๋ก์ ํธ ๊ตฌ์กฐ
image-filter-app/
โโโ src/
โ โโโ filters.c # WASM ํํฐ ๊ตฌํ
โ โโโ filters.h
โโโ web/
โ โโโ index.html
โ โโโ app.js
โ โโโ styles.css
โโโ build/
โ โโโ filters.wasm
โ โโโ filters.js
โโโ Makefile
Step 1: C๋ก ํํฐ ๊ตฌํํ๊ธฐ
// filters.c
#include <emscripten.h>
#include <math.h>
#include <stdlib.h>
// ์ธํผ์ ํํฐ
EMSCRIPTEN_KEEPALIVE
void applySepiaFilter(unsigned char* pixels, int width, int height) {
for(int i = 0; i < width * height * 4; i += 4) {
unsigned char r = pixels[i];
unsigned char g = pixels[i + 1];
unsigned char b = pixels[i + 2];
pixels[i] = fmin(255, (r * 0.393 + g * 0.769 + b * 0.189));
pixels[i + 1] = fmin(255, (r * 0.349 + g * 0.686 + b * 0.168));
pixels[i + 2] = fmin(255, (r * 0.272 + g * 0.534 + b * 0.131));
}
}
// ๋นํฐ์ง ํํฐ
EMSCRIPTEN_KEEPALIVE
void applyVintageFilter(unsigned char* pixels, int width, int height) {
for(int i = 0; i < width * height * 4; i += 4) {
unsigned char r = pixels[i];
unsigned char g = pixels[i + 1];
unsigned char b = pixels[i + 2];
// ์์ ์กฐ์
pixels[i] = fmin(255, r * 1.2);
pixels[i + 1] = fmin(255, g * 0.9);
pixels[i + 2] = fmin(255, b * 0.7);
// ๋น๋คํ
ํจ๊ณผ (๊ฐ์ฅ์๋ฆฌ ์ด๋ก๊ฒ)
int x = (i / 4) % width;
int y = (i / 4) / width;
float centerX = width / 2.0;
float centerY = height / 2.0;
float distance = sqrt(pow(x - centerX, 2) + pow(y - centerY, 2));
float maxDistance = sqrt(pow(centerX, 2) + pow(centerY, 2));
float vignette = 1.0 - (distance / maxDistance) * 0.5;
pixels[i] *= vignette;
pixels[i + 1] *= vignette;
pixels[i + 2] *= vignette;
}
}
// ๋ธ๋ฌ ํํฐ (๊ฐ๋จํ ๋ฐ์ค ๋ธ๋ฌ)
EMSCRIPTEN_KEEPALIVE
void applyBlurFilter(unsigned char* pixels, int width, int height, int radius) {
unsigned char* temp = (unsigned char*)malloc(width * height * 4);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
int sumR = 0, sumG = 0, sumB = 0, count = 0;
for(int dy = -radius; dy <= radius; dy++) {
for(int dx = -radius; dx <= radius; dx++) {
int nx = x + dx;
int ny = y + dy;
if(nx >= 0 && nx < width && ny >= 0 && ny < height) {
int idx = (ny * width + nx) * 4;
sumR += pixels[idx];
sumG += pixels[idx + 1];
sumB += pixels[idx + 2];
count++;
}
}
}
int idx = (y * width + x) * 4;
temp[idx] = sumR / count;
temp[idx + 1] = sumG / count;
temp[idx + 2] = sumB / count;
temp[idx + 3] = pixels[idx + 3];
}
}
// ๊ฒฐ๊ณผ ๋ณต์ฌ
for(int i = 0; i < width * height * 4; i++) {
pixels[i] = temp[i];
}
free(temp);
}
// ๋ฐ๊ธฐ ์กฐ์
EMSCRIPTEN_KEEPALIVE
void adjustBrightness(unsigned char* pixels, int width, int height, float factor) {
for(int i = 0; i < width * height * 4; i += 4) {
pixels[i] = fmin(255, pixels[i] * factor);
pixels[i + 1] = fmin(255, pixels[i + 1] * factor);
pixels[i + 2] = fmin(255, pixels[i + 2] * factor);
}
}
// ๋๋น ์กฐ์
EMSCRIPTEN_KEEPALIVE
void adjustContrast(unsigned char* pixels, int width, int height, float factor) {
float contrast = (259.0 * (factor + 255.0)) / (255.0 * (259.0 - factor));
for(int i = 0; i < width * height * 4; i += 4) {
pixels[i] = fmin(255, fmax(0, contrast * (pixels[i] - 128) + 128));
pixels[i + 1] = fmin(255, fmax(0, contrast * (pixels[i + 1] - 128) + 128));
pixels[i + 2] = fmin(255, fmax(0, contrast * (pixels[i + 2] - 128) + 128));
}
}
Step 2: JavaScript ์ธํฐํ์ด์ค
// app.js
class ImageFilterApp {
constructor() {
this.canvas = document.getElementById('canvas');
this.ctx = this.canvas.getContext('2d');
this.originalImageData = null;
this.wasmReady = false;
this.initWasm();
this.setupEventListeners();
}
async initWasm() {
const module = await import('./build/filters.js');
await module.default();
this.Module = module;
this.wasmReady = true;
console.log('WASM ๋ก๋ ์๋ฃ! ๐');
}
setupEventListeners() {
document.getElementById('fileInput').addEventListener('change',
(e) => this.loadImage(e));
document.getElementById('sepiaBtn').addEventListener('click',
() => this.applyFilter('sepia'));
document.getElementById('vintageBtn').addEventListener('click',
() => this.applyFilter('vintage'));
document.getElementById('blurBtn').addEventListener('click',
() => this.applyFilter('blur'));
document.getElementById('brightnessSlider').addEventListener('input',
(e) => this.adjustBrightness(e.target.value / 100));
document.getElementById('contrastSlider').addEventListener('input',
(e) => this.adjustContrast(e.target.value));
document.getElementById('resetBtn').addEventListener('click',
() => this.reset());
}
loadImage(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
this.canvas.width = img.width;
this.canvas.height = img.height;
this.ctx.drawImage(img, 0, 0);
this.originalImageData = this.ctx.getImageData(
0, 0, this.canvas.width, this.canvas.height
);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}
applyFilter(filterType) {
if(!this.wasmReady || !this.originalImageData) {
alert('์ด๋ฏธ์ง๋ฅผ ๋จผ์ ๋ก๋ํด์ฃผ์ธ์!');
return;
}
// ์๋ณธ ์ด๋ฏธ์ง ๋ฐ์ดํฐ ๋ณต์ฌ
const imageData = new ImageData(
new Uint8ClampedArray(this.originalImageData.data),
this.canvas.width,
this.canvas.height
);
const data = imageData.data;
const width = this.canvas.width;
const height = this.canvas.height;
// WASM ๋ฉ๋ชจ๋ฆฌ์ ๋ณต์ฌ
const dataPtr = this.Module._malloc(data.length);
this.Module.HEAPU8.set(data, dataPtr);
// ํํฐ ์ ์ฉ
const startTime = performance.now();
switch(filterType) {
case 'sepia':
this.Module._applySepiaFilter(dataPtr, width, height);
break;
case 'vintage':
this.Module._applyVintageFilter(dataPtr, width, height);
break;
case 'blur':
this.Module._applyBlurFilter(dataPtr, width, height, 3);
break;
}
const endTime = performance.now();
console.log(`ํํฐ ์ ์ฉ ์๊ฐ: ${(endTime - startTime).toFixed(2)}ms`);
// ๊ฒฐ๊ณผ ๊ฐ์ ธ์ค๊ธฐ
const resultData = this.Module.HEAPU8.subarray(dataPtr, dataPtr + data.length);
imageData.data.set(resultData);
this.ctx.putImageData(imageData, 0, 0);
this.Module._free(dataPtr);
}
adjustBrightness(factor) {
if(!this.wasmReady || !this.originalImageData) return;
const imageData = new ImageData(
new Uint8ClampedArray(this.originalImageData.data),
this.canvas.width,
this.canvas.height
);
const dataPtr = this.Module._malloc(imageData.data.length);
this.Module.HEAPU8.set(imageData.data, dataPtr);
this.Module._adjustBrightness(
dataPtr,
this.canvas.width,
this.canvas.height,
factor
);
const resultData = this.Module.HEAPU8.subarray(
dataPtr,
dataPtr + imageData.data.length
);
imageData.data.set(resultData);
this.ctx.putImageData(imageData, 0, 0);
this.Module._free(dataPtr);
}
adjustContrast(value) {
if(!this.wasmReady || !this.originalImageData) return;
const imageData = new ImageData(
new Uint8ClampedArray(this.originalImageData.data),
this.canvas.width,
this.canvas.height
);
const dataPtr = this.Module._malloc(imageData.data.length);
this.Module.HEAPU8.set(imageData.data, dataPtr);
this.Module._adjustContrast(
dataPtr,
this.canvas.width,
this.canvas.height,
parseFloat(value)
);
const resultData = this.Module.HEAPU8.subarray(
dataPtr,
dataPtr + imageData.data.length
);
imageData.data.set(resultData);
this.ctx.putImageData(imageData, 0, 0);
this.Module._free(dataPtr);
}
reset() {
if(this.originalImageData) {
this.ctx.putImageData(this.originalImageData, 0, 0);
}
}
}
// ์ฑ ์ด๊ธฐํ
window.addEventListener('DOMContentLoaded', () => {
new ImageFilterApp();
});
์ด ์ด๋ฏธ์ง ํํฐ ์ฑ์ ์์ JavaScript๋ก ๊ตฌํํ์ ๋์ ๋น๊ตํ๋ฉด, WASM ๋ฒ์ ์ด ํ๊ท 5-8๋ฐฐ ๋น ๋ฅด๊ฒ ๋์ํด์! ํนํ ๊ณ ํด์๋ ์ด๋ฏธ์ง๋ ๋ณต์กํ ํํฐ์ผ์๋ก ์ฐจ์ด๊ฐ ๋ ํฌ์ฃ .
๐ ์ค๋ฌด์์ ์์์ผ ํ ๊ณ ๊ธ ์ฃผ์ ๋ค
๊ธฐ๋ณธ์ ๋ค ๋ฐฐ์ ์ผ๋, ์ด์ ์ค๋ฌด์์ ์ ๋ง ์ค์ํ ๊ณ ๊ธ ์ฃผ์ ๋ค์ ์์๋ณผ๊น์? ๐1. ๋ฉํฐ์ค๋ ๋ฉ (Web Workers + WASM)
WASM์ Web Workers์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ง์ง ๋ณ๋ ฌ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํด์!// worker.js
importScripts('filters.js');
let wasmModule;
Module().then(module => {
wasmModule = module;
postMessage({ type: 'ready' });
});
onmessage = function(e) {
const { type, data, width, height } = e.data;
if(type === 'processImage') {
const dataPtr = wasmModule._malloc(data.length);
wasmModule.HEAPU8.set(data, dataPtr);
// ํํฐ ์ ์ฉ
wasmModule._applySepiaFilter(dataPtr, width, height);
const result = wasmModule.HEAPU8.slice(dataPtr, dataPtr + data.length);
wasmModule._free(dataPtr);
postMessage({
type: 'result',
data: result
}, [result.buffer]); // Transferable Objects ์ฌ์ฉ
}
};
// main.js
class ParallelImageProcessor {
constructor(numWorkers = 4) {
this.workers = [];
this.taskQueue = [];
for(let i = 0; i < numWorkers; i++) {
const worker = new Worker('worker.js');
worker.onmessage = (e) => this.handleWorkerMessage(e, i);
this.workers.push({
worker: worker,
busy: false
});
}
}
processImageParallel(imageData) {
return new Promise((resolve) => {
const width = imageData.width;
const height = imageData.height;
const numWorkers = this.workers.length;
const rowsPerWorker = Math.ceil(height / numWorkers);
const results = new Array(numWorkers);
let completed = 0;
for(let i = 0; i < numWorkers; i++) {
const startRow = i * rowsPerWorker;
const endRow = Math.min((i + 1) * rowsPerWorker, height);
const rows = endRow - startRow;
// ํด๋น ์์ปค๊ฐ ์ฒ๋ฆฌํ ๋ฐ์ดํฐ ์ถ์ถ
const sliceData = new Uint8ClampedArray(rows * width * 4);
for(let r = 0; r < rows; r++) {
const srcOffset = (startRow + r) * width * 4;
const dstOffset = r * width * 4;
sliceData.set(
imageData.data.subarray(srcOffset, srcOffset + width * 4),
dstOffset
);
}
this.workers[i].worker.postMessage({
type: 'processImage',
data: sliceData,
width: width,
height: rows,
workerId: i,
startRow: startRow
}, [sliceData.buffer]);
this.workers[i].worker.onmessage = (e) => {
results[e.data.workerId] = {
data: e.data.data,
startRow: e.data.startRow
};
completed++;
if(completed === numWorkers) {
// ๊ฒฐ๊ณผ ํฉ์น๊ธฐ
const finalData = new Uint8ClampedArray(
width * height * 4
);
results.forEach(result => {
const offset = result.startRow * width * 4;
finalData.set(result.data, offset);
});
resolve(new ImageData(finalData, width, height));
}
};
}
});
}
}
// ์ฌ์ฉ ์์
const processor = new ParallelImageProcessor(4);
const result = await processor.processImageParallel(imageData);
console.log('๋ณ๋ ฌ ์ฒ๋ฆฌ ์๋ฃ!');
2. SharedArrayBuffer๋ฅผ ํ์ฉํ ์ ๋ก ์นดํผ
SharedArrayBuffer๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ์ง ์๊ณ ์ฌ๋ฌ ์์ปค๊ฐ ๊ณต์ ํ ์ ์์ด์!// ๋ฉ์ธ ์ค๋ ๋
const sharedBuffer = new SharedArrayBuffer(width * height * 4);
const sharedArray = new Uint8ClampedArray(sharedBuffer);
// ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ๋ฒํผ์ ๋ณต์ฌ
sharedArray.set(imageData.data);
// ์์ปค๋ค์๊ฒ ๊ณต์ ๋ฒํผ ์ ๋ฌ
workers.forEach(worker => {
worker.postMessage({
type: 'setSharedBuffer',
buffer: sharedBuffer,
width: width,
height: height
});
});
SharedArrayBuffer๋ ๋ณด์์์ ์ด์ ๋ก ํน์ ํค๋ ์ค์ ์ด ํ์ํด์:
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp
3. ์คํธ๋ฆฌ๋ฐ ์ปดํ์ผ
ํฐ WASM ํ์ผ์ ๋ ๋น ๋ฅด๊ฒ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ด์์!// ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ (๋๋ฆผ)
const response = await fetch('large-module.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.compile(buffer);
// ์คํธ๋ฆฌ๋ฐ ์ปดํ์ผ (๋น ๋ฆ!)
const module = await WebAssembly.compileStreaming(fetch('large-module.wasm'));
// ์คํธ๋ฆฌ๋ฐ ์ธ์คํด์คํ (๋ ๋น ๋ฆ!!)
const { instance } = await WebAssembly.instantiateStreaming(
fetch('large-module.wasm'),
importObject
);
4. ๋์ ๋งํน
์ฌ๋ฌ WASM ๋ชจ๋์ ์กฐํฉํด์ ์ฌ์ฉํ ์ ์์ด์!// ๊ณตํต ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ชจ๋
const mathLib = await WebAssembly.instantiateStreaming(
fetch('math-lib.wasm')
);
// ๋ฉ์ธ ๋ชจ๋ (math-lib๋ฅผ import)
const mainModule = await WebAssembly.instantiateStreaming(
fetch('main.wasm'),
{
math: {
add: mathLib.instance.exports.add,
multiply: mathLib.instance.exports.multiply
}
}
);
๐ ์ฌ๋ฅ๋ท์์ WebAssembly ํ์ฉํ๊ธฐ
์ฌ๋ฌ๋ถ์ด ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ๊ณต์ ํ๊ฑฐ๋ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ฉด, WebAssembly๋ ์ ๋ง ์ข์ ์ฃผ์ ์์! ๐ฏ์ฌ๋ฅ๋ท์์ ์ ๊ณตํ ์ ์๋ WASM ๊ด๋ จ ์๋น์ค
1. ์ฑ๋ฅ ์ต์ ํ ์ปจ์คํ๊ธฐ์กด JavaScript ์ ํ๋ฆฌ์ผ์ด์ ์ WASM์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํด์ ์ฑ๋ฅ์ ํฅ์์์ผ๋๋ฆด ์ ์์ด์.
2. ์ปค์คํ WASM ๋ชจ๋ ๊ฐ๋ฐ
์ด๋ฏธ์ง ์ฒ๋ฆฌ, ๋ฐ์ดํฐ ์์ถ, ์ํธํ ๋ฑ ํน์ ๊ธฐ๋ฅ์ WASM์ผ๋ก ๊ตฌํํด๋๋ฆด ์ ์์ฃ .
3. ๊ต์ก ๋ฐ ๋ฉํ ๋ง
WASM์ ์ฒ์ ์ ํ๋ ๊ฐ๋ฐ์๋ค์๊ฒ 1:1 ๋ฉํ ๋ง์ ์ ๊ณตํ ์ ์์ด์.
4. ๋ ๊ฑฐ์ ์ฝ๋ ํฌํ
C/C++๋ก ์์ฑ๋ ๊ธฐ์กด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์น์์ ์ฌ์ฉํ ์ ์๋๋ก ํฌํ ํด๋๋ฆด ์ ์์ด์.
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ WASM ๊ด๋ จ ์ฌ๋ฅ์ ๊ฑฐ๋ํ ๋๋, ๊ตฌ์ฒด์ ์ธ ์ฑ๋ฅ ๊ฐ์ ์์น๋ ํฌํธํด๋ฆฌ์ค๋ฅผ ์ ์ํ๋ฉด ์ข์์. ์๋ฅผ ๋ค์ด "JavaScript ๋๋น 5๋ฐฐ ๋น ๋ฅธ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๊ตฌํ" ๊ฐ์ ์์ผ๋ก์!
๐ฎ WebAssembly์ ๋ฏธ๋
WASM์ ๊ณ์ ๋ฐ์ ํ๊ณ ์์ด์. ์์ผ๋ก ์ด๋ค ๊ธฐ๋ฅ๋ค์ด ์ถ๊ฐ๋ ์ง ์ดํด๋ณผ๊น์? ๐๐งต ์ค๋ ๋ ์ง์ (์๋ฃ)
์ด๋ฏธ ๋๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ์์ ์ง์ํ๊ณ ์์ด์. ์ง์ง ๋ฉํฐ์ค๋ ๋ฉ์ด ๊ฐ๋ฅํด์ก์ฃ !๐๏ธ ๊ฐ๋น์ง ์ปฌ๋ ์
WASM์์ ์ง์ GC๋ฅผ ์ง์ํ๋ ์ ์์ด ์งํ ์ค์ด์์. Kotlin, Dart ๊ฐ์ ์ธ์ด๋ค์ด ๋ ํจ์จ์ ์ผ๋ก ๋์ํ ์ ์๊ฒ ๋ ๊ฑฐ์์.๐ ์ปดํฌ๋ํธ ๋ชจ๋ธ
WASM ๋ชจ๋๋ค์ ๋ ์ฝ๊ฒ ์กฐํฉํ๊ณ ์ฌ์ฌ์ฉํ ์ ์๋ ํ์ค์ด ๊ฐ๋ฐ ์ค์ด์์.๐ WASI (WebAssembly System Interface)
๋ธ๋ผ์ฐ์ ๋ฐ์์๋ WASM์ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ํ์ค์ด์์. ์๋ฒ์ฌ์ด๋์์๋ WASM์ ์ฌ์ฉํ ์ ์์ฃ !๐ฎ WebGPU ํตํฉ
GPU ๊ฐ์์ ๋ ํจ์จ์ ์ผ๋ก ํ์ฉํ ์ ์๊ฒ ๋ ๊ฑฐ์์. ๊ฒ์์ด๋ ๋จธ์ ๋ฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํฐ ๋์์ด ๋๊ฒ ์ฃ !๐ฆ ์์ธ ์ฒ๋ฆฌ
C++์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ์ง์ํ๋ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋ ์์ ์ด์์.๐ ํ์ต ๋ฆฌ์์ค์ ์ปค๋ฎค๋ํฐ
WASM์ ๋ ๊น์ด ๊ณต๋ถํ๊ณ ์ถ๋ค๋ฉด ์ด๋ฐ ๋ฆฌ์์ค๋ค์ ํ์ฉํด๋ณด์ธ์! ๐๊ณต์ ๋ฌธ์ ๋ฐ ํํ ๋ฆฌ์ผ
๐ WebAssembly.org๊ณต์ ์น์ฌ์ดํธ๋ก, ์คํ๊ณผ ๊ธฐ๋ณธ ํํ ๋ฆฌ์ผ์ด ์์ด์.
๐ MDN Web Docs
Mozilla์์ ์ ๊ณตํ๋ ์์ธํ ๋ฌธ์์ ์์ ๋ค์ด ์์ด์.
๐ฆ Rust and WebAssembly Book
Rust๋ก WASM์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์์ธํ ์ค๋ช ํด์ค์.
๐ง Emscripten Documentation
C/C++๋ฅผ WASM์ผ๋ก ์ปดํ์ผํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ธ ์ ์์ด์.
์จ๋ผ์ธ ๊ฐ์ ๋ฐ ์ฝ์ค
Udemy, CourseraWebAssembly ๊ด๋ จ ๊ฐ์๋ค์ด ๋ง์ด ์์ด์.
YouTube
๋ฌด๋ฃ ํํ ๋ฆฌ์ผ๊ณผ ์ปจํผ๋ฐ์ค ๋ฐํ ์์๋ค์ ๋ณผ ์ ์์ด์.
Frontend Masters
๊ณ ๊ธ ์น ๊ฐ๋ฐ ์ฃผ์ ๋ค์ ๋ค๋ฃจ๋ ํ๋ซํผ์ด์์.
์ปค๋ฎค๋ํฐ
Reddit - r/WebAssemblyWASM ๊ฐ๋ฐ์๋ค์ด ๋ชจ์ฌ์ ์ ๋ณด๋ฅผ ๊ณต์ ํ๋ ๊ณณ์ด์์.
Discord - WebAssembly Community
์ค์๊ฐ์ผ๋ก ์ง๋ฌธํ๊ณ ๋ต๋ณ๋ฐ์ ์ ์์ด์.
Stack Overflow
WASM ๊ด๋ จ ์ง๋ฌธ๋ค์ด ๋ง์ด ์ฌ๋ผ์ ์์ด์.
โ ๏ธ ์ฃผ์์ฌํญ๊ณผ ๋ฒ ์คํธ ํ๋ํฐ์ค
WASM์ ์ฌ์ฉํ ๋ ๊ผญ ์์์ผ ํ ์ฃผ์์ฌํญ๋ค์ด์์! ๐จ1. WASM์ด ํญ์ ๋ต์ ์๋์์
WASM์ ์ฌ์ฉํ๋ฉด ์ข์ ๊ฒฝ์ฐ:โ CPU ์ง์ฝ์ ์ธ ๊ณ์ฐ (์ด๋ฏธ์ง ์ฒ๋ฆฌ, ๊ฒ์ ๋ฌผ๋ฆฌ, ์ํธํ)
โ ๊ธฐ์กด C/C++ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฌ์ฉ
โ ์ฑ๋ฅ์ด ์ ๋ง ์ค์ํ ๊ฒฝ์ฐ
JavaScript๊ฐ ๋ ๋์ ๊ฒฝ์ฐ:
โ DOM ์กฐ์์ด ๋ง์ ๊ฒฝ์ฐ
โ ๊ฐ๋จํ ๋น์ฆ๋์ค ๋ก์ง
โ ๋คํธ์ํฌ I/O๊ฐ ๋ณ๋ชฉ์ธ ๊ฒฝ์ฐ
โ ๋น ๋ฅธ ํ๋กํ ํ์ดํ์ด ํ์ํ ๊ฒฝ์ฐ
2. ํ์ผ ํฌ๊ธฐ ๊ณ ๋ คํ๊ธฐ
WASM ํ์ผ์ด ๋๋ฌด ํฌ๋ฉด ๋ก๋ฉ ์๊ฐ์ด ๊ธธ์ด์ ธ์. ์ต์ ํ ์ต์ ์ ์ ํ์ฉํ์ธ์!# ํฌ๊ธฐ ์ต์ ํ
emcc -Oz --closure 1 -s FILESYSTEM=0 mycode.c -o mycode.js
# gzip ์์ถ ํ์ฉ
gzip -9 mycode.wasm
3. ๋ธ๋ผ์ฐ์ ํธํ์ฑ ์ฒดํฌ
๋๋ถ๋ถ์ ์ต์ ๋ธ๋ผ์ฐ์ ๋ WASM์ ์ง์ํ์ง๋ง, ํญ์ ์ฒดํฌํ์ธ์!if(typeof WebAssembly === 'object') {
// WASM ์ง์
loadWasmModule();
} else {
// ํด๋ฐฑ ๋ก์ง
loadJavaScriptVersion();
}
4. ๋ฉ๋ชจ๋ฆฌ ๋์ ์ฃผ์
WASM์์ ํ ๋นํ ๋ฉ๋ชจ๋ฆฌ๋ ๋ฐ๋์ ํด์ ํด์ผ ํด์!class WasmMemoryManager {
constructor() {
this.allocations = new Set();
}
malloc(size) {
const ptr = Module._malloc(size);
this.allocations.add(ptr);
return ptr;
}
free(ptr) {
Module._free(ptr);
this.allocations.delete(ptr);
}
freeAll() {
this.allocations.forEach(ptr => Module._free(ptr));
this.allocations.clear();
}
}
const memManager = new WasmMemoryManager();
5. ๋๋ฒ๊น ์ ๋ณด ํฌํจํ๊ธฐ
๊ฐ๋ฐ ์ค์๋ ๋๋ฒ๊น ์ ๋ณด๋ฅผ ํฌํจ์์ผ์ ์ปดํ์ผํ์ธ์!# ๊ฐ๋ฐ ๋น๋
emcc -g4 --source-map-base ./ mycode.c -o mycode.js
# ํ๋ก๋์
๋น๋
emcc -O3 mycode.c -o mycode.js
๐ฌ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์! ์ฌ๊ธฐ๊น์ง ์ฝ์ผ์ จ๋ค๋ ์ ๋ง ๋๋จํด์! ๐WebAssembly๋ ์น ๊ฐ๋ฐ์ ํ๋๋ฅผ ๋ฐ๊พธ๊ณ ์๋ ํ์ ์ ์ธ ๊ธฐ์ ์ด์์. ๋ค์ดํฐ๋ธ ์์ค์ ์ฑ๋ฅ์ ์น์์ ๊ตฌํํ ์ ์๋ค๋ ๊ฑด ์ ๋ง ๋๋ผ์ด ์ผ์ด์ฃ !
๐ฏ ํต์ฌ ์์ฝ
1. WASM์ ๋น ๋ฅด๋คJavaScript๋ณด๋ค 2-20๋ฐฐ ๋น ๋ฅธ ์คํ ์๋๋ฅผ ์๋ํด์.
2. ๋ค์ํ ์ธ์ด ์ง์
C, C++, Rust, Go ๋ฑ ์ฌ๋ฌ ์ธ์ด๋ก ์์ฑํ ์ ์์ด์.
3. JavaScript์ ํ๋ ฅ
WASM์ JavaScript๋ฅผ ๋์ฒดํ๋ ๊ฒ ์๋๋ผ ๋ณด์ํ๋ ๊ธฐ์ ์ด์์.
4. ์ค์ ํ์ฉ ๊ฐ๋ฅ
๊ฒ์, ์ด๋ฏธ์ง ์ฒ๋ฆฌ, ๋ฐ์ดํฐ ๋ถ์ ๋ฑ ๋ค์ํ ๋ถ์ผ์์ ํ์ฉ๋๊ณ ์์ด์.
5. ๊ณ์ ๋ฐ์ ์ค
์๋ก์ด ๊ธฐ๋ฅ๋ค์ด ๊ณ์ ์ถ๊ฐ๋๊ณ ์์ด์.
1. ๊ฐ๋จํ ์์ ๋ถํฐ ์์ํด๋ณด์ธ์
2. ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด์ธ์
3. ์ฑ๋ฅ์ ์ธก์ ํ๊ณ ์ต์ ํํ์ธ์
4. ์ปค๋ฎค๋ํฐ์ ์ฐธ์ฌํด์ ๊ฒฝํ์ ๊ณต์ ํ์ธ์
5. ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ ์ฌ๋ฌ๋ถ์ ์ง์์ ๋๋ ๋ณด์ธ์!
์ฌ๋ฌ๋ถ๋ ์ด์ WASM ์ ๋ฌธ๊ฐ๊ฐ ๋์ด์, ๋ ๋น ๋ฅด๊ณ ๊ฐ๋ ฅํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค์ด๋ณด์ธ์! ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ ๊ฒฝํ๊ณผ ์ง์์ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ๊ณต์ ํด๋ณด๋ ๊ฑด ์ด๋จ๊น์? ๐
๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ๋์์ด ํ์ํ๋ฉด ์ธ์ ๋ ์ง ์ปค๋ฎค๋ํฐ์ ์ง๋ฌธํด๋ณด์ธ์. ์ฐ๋ฆฌ ๋ชจ๋ ํจ๊ป ์ฑ์ฅํ๋ ๊ฑฐ๋๊น์! ๐ช
Happy Coding! ์ฆ๊ฑฐ์ด ์ฝ๋ฉ ๋์ธ์! ๐
๊ด๋ จ ํค์๋
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.

๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.