본문으로 건너뛰기
yceffort
PostsSeriesTagsAbout🧪 Research
EN

Tweaks

theme
accent palette
film grain
minimal mode
BACK TO INDEX
◆ ESSAY
--min
--year
KOoriginal

mailMail icongithubtwitter
yceffort
•
© 2026
•
https://yceffort.kr
BACK TO INDEX
◆ ESSAY

Rust로 web assembly 만들어보기 (3) - Rust로 다양한 Web Assembly 만들어보기

avatar
yceffort
2022-03-11 · 3분
3min
2022year
KOoriginal
rustwebassembly

Table of Contents

  • Console.log를 기록하는 wasm 만들어보기
  • 번들러 없이 직접 import 해서 사용하기
  • js 코드를 import 해서 rust에서 실행하기

Console.log를 기록하는 wasm 만들어보기

Cargo.toml

[package]
name = "consolelog"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
wasm-bindgen = "0.2.74"
web-sys = { version = "0.3.56", features = ['console'] }

lib.rs

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern {
    // js_namespace는 console을 할당했다.
    // 즉 log만 쓰면 console.log가 된다.
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);

    // 여기는 console.log
    #[wasm_bindgen(js_namespace=console, js_name=log)]
    fn log_u32(a: u32);

    // 여기도 console.log
    #[wasm_bindgen(js_namespace=console, js_name=log)]
    fn log_strings(a: &str, b: &str);
}

macro_rules! console_log {
    // log 함수랑 연결된다.
    ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}

// rust extern으로 하는 방법
fn rust() {
    log("Hello yceffort!");
    log_u32(42);
    log_strings("Hello", "yceffort")
}

// macro
fn using_macro() {
    console_log!("Hello {}!", "yceffort");
    console_log!("Hello yceffort");
}

// websys library
fn using_web_sys() {
    use web_sys::console;

    console::log_1(&"Hello using web-sys".into());

    let js: JsValue = 4.into();

    console::log_2(&"Logging values are".into(), &js);
}

#[wasm_bindgen(start)]
pub fn run() {
    rust();
    using_macro();
    using_web_sys();
}

번들러 없이 직접 import 해서 사용하기

Cargo.toml

[package]
name = "without-bundler"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.79"

[dependencies.web-sys]
version = "0.3.4"
features = [
  'Document',
  'Element',
  'HtmlElement',
  'Node',
  'Window',
]

lib.rs

use wasm_bindgen::prelude::*;

#[wasm_bindgen(start)]
pub fn main() {
    let window = web_sys::window().expect("there is no window in global");
    let document = window.document().expect("there is no document in window");
    let body = document.body().expect("there is no body in a document");

    let p_element = document.create_element("p").expect("fail to create P element");

    p_element.set_inner_html("Hello from rust");

    body.append_child(&p_element).expect("fail to append element");
}

#[wasm_bindgen]
pub fn add(a: u32, b: u32) -> u32 {
    a + b
}

js 코드를 import 해서 rust에서 실행하기

가령 자바스크립트에 아래와 같은 코드가 있다고 가정해보자.

defined-in-js.js

export function name() {
  return 'Rust'
}

export class MyClass {
  constructor() {
    this._number = 42
  }

  get number() {
    return this._number
  }

  set number(n) {
    return (this._number = n)
  }

  toString() {
    return `My number is: ${this.number}`
  }
}

위 코드를 rust에서 실행하기 위해서는 먼저 해당 js코드를 추상화하는 작업이 필요하다. 위 코드에 대한 추상화는 아래와 같이 작업하면 된다.

use wasm_bindgen::prelude::*;

#[wasm_bindgen(module = "/defined-in-js.js")]
extern "C" {
    // name 함수 정의
    fn name() -> String;

    // 클래스 정의
    type MyClass;

    // 클래스에 new keyword를 constructor로 정의
    #[wasm_bindgen(constructor)]
    fn new() -> MyClass;

    // getter
    #[wasm_bindgen(method, getter)]
    fn number(this: &MyClass) -> u32;

    // setter
    #[wasm_bindgen(method, setter)]
    fn set_number(this: &MyClass, number: u32) -> MyClass;

    // toString
    #[wasm_bindgen(method)]
    fn toString(this: &MyClass) -> String;
}

// console.log를 정의한다.
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

#[wasm_bindgen(start)]
pub fn run() {
    log(&format!("Hello from {}!", name())); // should output "Hello from Rust!"

    // 클래스를 선언한다
    let x = MyClass::new();
    // 테스트 코드!
    assert_eq!(x.number(), 42);
    // setter에 숫자 주입
    x.set_number(10);
    // toString
    log(&x.toString());
}

run() 함수 내부에 있는 것들이 순차적으로 실행될 것이다.

Hello from Rust!
My number is: 10

관련 글

  • #rust#webassembly

    Rust로 web assembly로 game of life 만들어보기 (2)

    사이드 프로젝트도 열심히 하고 싶은데 바쁘기도 바쁘고 체력도 안되는 것 같고 아무튼 핑계입니다.

    2022-04-08·17분
  • #rust#webassembly

    Rust로 web assembly로 game of life 만들어보기 (1)

    코로나 휴가를 틈탄 러스트 뻘짓

    2022-03-18·7분
  • #rust#webassembly

    Rust로 web assembly 만들어보기 (2) - Rust로 간단한 Web Assembly 만들기

    오 이거 신기하네

    2022-03-10·7분
  • #rust#webassembly

    Rust로 web assembly 만들어보기 (1) - Web Assembly란 무엇인가?

    인생은 실전이다

    2022-03-07·7분

새 글을 놓치고 싶지 않으시다면 RSS로 구독해 주세요.

RSS 구독 →

yceffort — 프론트엔드 엔지니어입니다. 발표·기술 자문·기고 문의는 이곳에서 받고 있습니다.

← Back to the blogIssue on GitHub →