|
웹 어셈블리를 설명하고, 러스트로 간단한 웹 어셈블리 응용 프로그램을 작성하는 방법을 설명합니다. |
들어가며
안녕하세요. VD사업부 S/W Platform Lab의 김백기입니다. 알면 알수록 웹 어셈블리 (WebAssembly, 간단히 Wasm)는 혁신적인 기술입니다. 2015년 4월, 웹 어셈블리 커뮤니티 그룹(WebAssembly Community Group)에서 처음 발표한 이 기술은, “웹에 컴파일하는데 더 적합하고, 크기와 로드 시간이 더 효율적인 새로운 포맷에 대한 초기 단계의 브라우저 간 협업을 촉진한다”는 사명을 가지고 만든 것으로 알려져 있습니다. 웹 어셈블리를 사용하면 웹 브라우저에서 C, C++, C#, 러스트와 같은 코드를 실행하여 이전에는 불가능했던 고성능 웹 애플리케이션을 구현할 수 있습니다. 또한 기존 웹에 주로 사용되었던 JavaScript를 보완하여 고성능 작업을 수행하도록 할 수 있습니다.
wasm은 웹에서 사용 가능한 유일한 Low-level Language* [2]
웹 어셈블리는 웹 개발의 새로운 패러다임을 제시하며 더 빠르고 안전하며 풍부한 웹 경험을 사용자에게 제공합니다. JavaScript 중심의 기존 웹 개발 패턴을 넘어 다양한 언어와 도구를 활용해 복잡하고 기능이 풍부한 웹 애플리케이션을 구축하는 데 중요한 역할을 하고 있습니다.
웹 어셈블리의 주요 특징 중 하나는 다양한 고수준 프로그래밍 언어로 작성된 코드를 언어 중립적인 바이트 코드(Bytecode)로 컴파일하는 것입니다. 이 바이트 코드는 웹 브라우저에서 바로 실행할 수 있고, JavaScript와 비슷한 빠른 속도로 실행됩니다. 뒤이어 나오는 ‘웹 어셈블리의 작동 과정’에서 보다 자세히 설명하겠습니다.
웹 어셈블리는 스택 기반 가상 머신에서 동작합니다. 이는 명령어가 가상 스택을 사용하여 실행된다는 것을 의미합니다. 이 접근 방식은 실행 효율을 높이고, 메모리 관리를 간소화하며, 다양한 언어 간의 호환성을 높일 수 있습니다. 이러한 웹 어셈블리의 특성 덕분에 웹 상에서 복잡한 계산, 그래픽 처리, 게임, 실시간 애플리케이션과 같은 고성능 작업을 실행하고 다양한 프로그래밍 언어와 툴체인을 사용할 수 있게 되었습니다.
이 포스팅은 독자가 러스트(Rust) 프로그래밍 언어에 익숙하다는 가정하에 작성하였습니다. 러스트의 기본 문법은 ‘러스트 프로그래밍 공식 가이드1’를 참고해 주세요.
1전문은 https://rinthel.github.io/rust-lang-book-ko/에서 확인 가능합니다.
웹 어셈블리의 장단점
웹 어셈블리는 분명히 장점이 뛰어난 기술이지만 단점도 있습니다. 이 기술의 장단점을 함께 살펴보겠습니다.
웹 어셈블리의 장점
- 성능: 웹 어셈블리는 주로 게임이나 물리 시뮬레이션처럼 복잡한 수치 계산이 필요한 작업에서 JavaScript보다 빠른 성능을 제공합니다. 웹 어셈블리를 사용하면 일반적으로 JavaScript보다 성능이 뛰어난 C, C++, Rust 및 기타 정적 언어로 작성된 코드를 웹으로 가져올 수 있습니다.
- 이식성: 웹 어셈블리로 만들어진 코드는 웹 어셈블리 인터프리터를 지원하는 모든 플랫폼에서 실행할 수 있습니다. 웹 어셈블리로 컴파일된 코드는 이론적으로 어디에서나 실행 가능하므로 여러 플랫폼을 대상으로 개발하는 개발자에게 유리합니다.
- 언어 간 상호 윤용성: 웹 어셈블리는 특정 언어에 구애받지 않으므로 개발자는 웹 개발을 위해 JavaScript만 사용할 필요가 없습니다. 개발자는 C, C++ 또는 Rust와 같은 언어로 코드를 작성할 수 있고, 이렇게 작성된 코드는 특정 시나리오에서 JavaScript보다 다양한 이점을 제공할 수 있습니다.
웹 어셈블리의 단점
- 디버깅: 웹 어셈블리 코드를 디버깅하는 것은 JavaScript 디버깅보다 어려울 수 있습니다. 아직까지 디버깅 도구가 완전히 발전되지 않았고, WebAssembly는 저수준 바이너리 형식이기 때문에 JavaScript보다 접근성과 가독성이 떨어집니다.
- 개발 복잡성: C++ 또는 Rust와 같은 언어로 코드를 작성한 다음 WebAssembly로 컴파일하는 것은 일반적으로 JavaScript를 작성하는 것보다 더 복잡합니다. 이는 잠재적으로 더 높은 성능을 제공할 수 있지만 진입 장벽도 높아집니다.
웹 어셈블리의 작동 과정
웹 어셈블리의 작동 과정은 아래와 같이 도식화할 수 있으며, 구현, 컴파일, 구동의 세 단계로 구성됩니다.
그림 1 WebAssembly 구조도
위 다이어그램을 자세히 설명하면 아래와 같습니다.
|
단계
|
주체
|
내용
|
|
|---|---|---|---|
|
구현
|
개발자
|
개발자는 C/C++ 또는 러스트와 같은 언어를 사용하여
원하는 로직을 구현합니다. |
|
|
컴파일
|
빌드 시스템
|
IR: LLVM 프론트엔드 컴파일러는 IR(Intermediate
Representation)이라는 중간 언어를 사용하여 개발자의 소스코드를 컴파일합니다. wasm: LLVM 백엔드 컴파일러가 IR을 사용하여 웹 어셈블리 이진 표현인 wasm 파일을 생성합니다. 이 파일은 웹 브라우저에서 로드하여 실행할 수 있는 바이트 코드(Bytecode)를 포함하고 있습니다. |
|
|
실행
|
브라우저
|
컴파일러가 생성한 wasm 파일을 웹 브라우저가 로드하고
실행합니다. 이 과정에서 wasm 모듈은 JavaScript와 상호 작용할 수 있습니다. |
|
웹 어셈블리 개발하기
웹 어셈블리를 개발하기 전에 개발 환경을 구성해야 합니다. 이 과정에서 필요한 컴파일러, 툴체인, 라이브러리 및 의존성을 설치하고 설정합니다. 아쉽게도 아직은 웹 어셈블리를 지원하는 cargo 크레이트가 많지 않아 때로는 빌드 오류가 발생할 수 있습니다.
1. 개발 환경 구성
우선 wasm pack을 설치해야 합니다. wasm pack은 러스트에서 wasm을 빌드하고 패키징할 수 있게 해 주는 강력한 도구입니다. 이 도구는 러스트와 웹 어셈블리 간의 효율적인 연결을 지원하며, 러스트 프로젝트를 쉽게 웹에서 실행할 수 있는 형태로 변환하는 데 필수적입니다. wasm pack을 사용하면 러스트 코드를 웹 어셈블리 모듈로 빠르고 간편하게 컴파일할 수 있으며, 개발, 테스트, 배포 단계에서도 편리한 기능을 제공합니다.
간혹 버전 차이로 openssl 설치 오류가 발생할 경우, 아래와 같이 기본 설치되는 패키지 설치를 무시하고 본 챕터를 진행해도 문제가 되지 않습니다.
2. 간단한 웹 어셈블리 만들기
먼저 라이브러리 크레이트를 만듭니다.
#[wasm_bindgen]이라는 함수 어노테이션을 사용하여 wasm으로 노출시킬 함수들을 정의합니다. 여기서는 hello 함수를 노출시키겠습니다. alert 함수는 브라우저의 alert 함수입니다.
• 예제 1 WebAssembly 바인딩 코드
Cargo.toml 파일을 열어 wasm-bindgen의 의존성을 추가합니다.
이제 wasm-pack으로 빌드해보겠습니다.
pkg 폴더에 wasm 파일들이 생성된 것을 확인할 수 있습니다.
3. wasm을 구동할 웹 서버 설정
wasm은 웹 브라우저에서 실행되기 때문에 사용하려면 간단한 웹 페이지와 웹 서버가 필요합니다. 웹 페이지는 웹 어셈블리 모듈을 로드하고 실행하는 역할을 하고, 웹 서버는 해당 웹 페이지와 웹 어셈블리 파일을 호스팅하고 클라이언트 요청에 응답합니다. 로컬 개발 환경에서는 간단한 개발용 웹 서버를 사용하여 테스트와 디버깅을 수행할 수 있으며, 실제 배포 시에는 적절한 웹 서버 설정과 보안에 대한 고려가 필요합니다. 서버 설정과 보안 부분은 이 포스팅의 범위를 넘어서기에 여기서는 설명하지 않겠습니다.
index.html을 아래와 같이 구성해 보겠습니다. 프로젝트의 최상위 폴더에 static 폴더를 별도로 만들고 해당 폴더에 웹 서비스 관련 파일들을 배포하는 것이 편리하고 관리하기 쉽습니다.
• 예제 2 index.html 구성
시스템에 설치된 웹 서버가 없다면 단순한 웹 서버인 nodejs기반 http-server를 사용할 수 있습니다. 여기서는 http-server를 사용하겠습니다. 아래와 같이 npm 명령을 사용하여 http-server를 설치합니다.
http-server를 구동합니다.
웹 브라우저를 사용해 http://127.0.0.1:8080/static/index.html에 접속합니다.
그림 2 WebAssembly 샘플 실행 결과
러스트 함수인 hello가 정상적으로 호출되었습니다.
결론
우리는 웹 어셈블리의 강력한 기능을 탐구하면서 이 기술의 중요성과 잠재력을 이해할 수 있었는데요. 웹 어셈블리의 개념과 기본 원리, 그리고 웹 어셈블리가 왜 중요한지에 대해 설명하였고, 웹 어셈블리의 내부 구조와 작동 방식을 예제를 통해 알아보기도 했습니다.
웹 어셈블리는 웹 플랫폼에 있어서 상당히 중요한 의미를 갖습니다. 여러 언어로 작성된 코드들을 네이티브에 가까운 속도로 웹에서 돌릴 수 있는 해결책을 제공하고, 이전까지는 웹에서 돌려볼 수 없었던 클라이언트 앱들을 웹에서 돌릴 수 있도록 만들어 줍니다. JavaScript와 함께 보완되고 실행되도록 설계되었기에 WebAssembly JavaScript API를 사용하여 WebAssembly 모듈을 JavaScript 앱에 불러와 둘 사이의 기능을 공유할 수도 있습니다.
따라서 WebAssembly 코드를 작성하는 방법을 몰라도 WebAssembly의 성능과 JavaScript의 편리함 및 유연성을 하나의 애플리케이션에서 활용할 수 있는 것이죠. 주요 브라우저 벤더의 적극적인 참여를 통해 W3C 웹 어셈블리 워킹 그룹 및 Community Group에서 웹 표준으로 개발되고 있다는 점도 기억하면 좋을 것입니다. ‘만화로 소개하는 웹 어셈블리’라는 좋은 자료도 있으니 편한 마음으로 웹 어셈블리의 세계를 들여다보아도 좋겠습니다.
감사합니다. VD사업부 S/W Platform Lab 김백기입니다.
|
|
