들어가며

어디선가 간단히 보고 지나간 것 같은 웹 어셈블리.

실제로 web3 지갑 발행 관련 로직이 있었지만 암호화라던지, 이런 저런 연산을 프론트에서 다 하는게 맞나? 싶어서 서버에서 돌려보는건 어떨까 생각했지만…

결국 유저의 지갑 정보는 유저만 가진다 이게 탈 중앙화의 가치라고 생각했기에 어떻게든지 유저의 기기에서 작동시켜야만 했다.

따라서 구현 후 개념에 대해서 자세히 공부해보았다.

웹 어셈블리?

WebAssembly (WASM) 은 웹 브라우저에서 네이티브에 가까운 성능으로 코드를 실행할 수 있게 해주는 바이너리 명령어 형식이자, 스택 기반 가상 머신을 위한 표준이다

즉 유일한 웹의 언어였던 JavaScript 외에도 C, C++, Rust, Go 등 다양한 언어로 작성된 프로그램을 웹 브라우저에서 실행할 수 있도록 변환해주는 컴파일 타깃이다.

WASM은 CPU가 처리하기 쉬운 저수준(Low-Level) 바이너리 형식이다.

등장 배경

1. JS의 성능적 한계

JS는 동적 타입 언어 + 인터프리터 방식으로 시작함.

V8 엔진 등 JIT 컴파일을 통해 성능이 개선되었음에도, 물리, 이미지/비디오 편집 같은 CPU 집약적 작업에는 근본적 한계가 있었다.

2. W3C 웹 표준

주요 브라우저 벤더들이 합의한 웹 표준! 특정 브라우저의 기능에 기댄 기능이 아닌, 모든 웹 (대부분) 브라우저에서 예측 가능하고 일관적인 성능을 기대할 수 있게 됨

성능적 우위를 가지는 이유

  1. 바이너리 형식으로 제공되어 js 다운로드 -> 컴파일 -> 파싱 -> 로딩과 같은 과정보다 빠름.
  2. AOT 방식으로 빠르게 기계어로 변환 (타입 추론과 같은 과정에 대해 이점을 지님)

내부 구조와 동작 방식

WASM은 스택 기반 가상 머신(stack-based VM) 위에서 실행된다.

즉, 명령어들이 “스택”을 중심으로 연산을 수행하는 형태이며, C/C++/Rust 코드를 브라우저에서 동작 가능한 .wasm 바이너리 파일로 변환한 뒤 로드된다.

실행 과정은 다음과 같다.

  1. 코드 작성 (C/Rust 외)
  2. wasm 컴파일
  3. 브라우저에서 로딩
  4. JS와 상호작용 하며 결과 반환

rust 기준 필요한 것 + 빌드까지

cargo install wasm-pack
wasm-pack build --target web

WASM에 대한 오해

1. JavaScript를 대체한다.

대체하기 보다는 보완하는 역할에 가깝다. CPU 집약 연산에 강하지만, 여전히 API 접근이나 DOM 조작은 JS를 통해 이루어져야 한다.

2. JavaScript보다 항상 빠르다.

CPU 집약적 연산에 빠르다.

작은 모듈의 로딩과 초기화는 오히려 JS의 JIT 컴파일이 빠를 수 있음. 오히려 wasm은 연산량이 커지며 복잡해지는 경우 효율적이다.

추가적으로 JS에서 WASM으로 데이터 전송을 하는 (내부 과정이긴 하지만) 비용이 생각보다 비싸다. (오래걸린다)

쉽고 반복적인 작업은 JavaScript에서 처리하자.

마무리하며

일단 간단히 알아본만큼

MDN 문서를 읽어보는 것도 좋을 것 같다.

큰 기업들에서도 관련해서 블로그 포스팅과 같은걸 작성했던데

MDN - webassembly