WebAssembly란
웹 브라우저에서 작동되는 프로그래밍 언어로, webAssembly 자체로 코드를 작성하기보다 C, C++, Rust등의 소스 언어를 컴파일하는 타겟 언어로써 고안되었다.
브라우저에서 실행할 때는 javascript에서 webAssembly를 실행시키는 코드를 작성해 네이티브에 가까운 속도로 실행시킬 수 있다.
그럼 이 webAssembly로 컴파일된 함수를 node에서 사용하면 어떨까?
함수 작성
성능 비교를 위해 백엔드 서버에서 해시 함수를 사용하는 상황을 가정하고, 다음과 같은 해시함수를 작성한다.
export default function generateHash(input) {
let hash = 2166136261;
for (let i = 0; i < input.length; i++) {
const charCode = input.charCodeAt(i);
for (let j = 0; j < 100000; j++) {
hash ^= charCode;
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
}
}
return hash;
}
이 함수는 시행 시간을 측정하기 용이하게 일부러 매우 비효율적으로 작성했고, 이제 이를 wasm으로 빌드하기 위해서 assemblyScript로 옮겨 작성한다.
export function generateHash(input: string): i32 {
let hash: i32 = 2166136261;
for (let i: i32 = 0; i < input.length; i++) {
const charCode: i32 = input.charCodeAt(i);
for (let j: i32 = 0; j < 100000; j++) {
hash ^= charCode;
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
}
}
return hash;
}
assemblyscript파일을 wasm파일로 컴파일하기 위해선 다음 명령어를 사용한다.
// hash.ts는 assemblyScript 원본 파일, hash.wasm은 타겟 파일
> asc hash.ts -o hash.wasm
node에서 함수 불러오기
node에서 기본적으로 wasm모듈을 불러오는 기능을 지원하나, wasm 모듈을 assemblyscript로 빌드했기 때문에 여러 편의성을 제공하는 assemblyscript 패키지를 별도로 설치했다.
import loader from "@assemblyscript/loader";
import fs from "fs/promises";
const loadWasmModule = async () => {
const file = await fs.readFile("./src/modules/common/hash.wasm");
wasmModule = await loader.instantiate(file);
};
const runWasmHash = (password) => {
const { __newString, generateHash } = wasmModule.exports;
return generateHash(__newString(password));
};
실행 시간 비교
wasm으로 작성된 함수가 훨씬 빠른 시간 안에 실행됨을 알 수 있었다.
ffi와의 차이점
ffi | wasm | |
로드 | 오버헤드가 큼 | instantiate 이후는 쉬움 |
디버깅 | 디버깅 어려움(고수준의 native 이해 필요) | 디버깅 쉬움 |
확장 | 어려움 | 브라우저에서 동작가능 |
레퍼런스
한글로 되어있는 레퍼런스가 없어서 힘들었다...
https://nodejs.org/en/learn/getting-started/nodejs-with-webassembly (nodejs docs)
https://www.assemblyscript.org/getting-started.html#setting-up-a-new-project (assemblyScript)
https://github.com/AssemblyScript/assemblyscript/tree/main/lib/loader (loader)
'개발 > 백엔드' 카테고리의 다른 글
[nestjs] AWS S3를 이용한 이미지 업로드 (0) | 2024.05.21 |
---|---|
[nestjs] 프로젝트에 prisma 추가하기 (2) | 2023.10.20 |
[nestjs] postgresql을 이용한 crud 구현 (0) | 2023.08.23 |
[nestjs] 로그인과 권한 부여 (0) | 2021.12.20 |
[nestjs] socket.io 사용과 테스트 (0) | 2021.11.01 |