Design: ์–ธ์ œ ๊ธ€๋ฃจ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๊นŒ?

์— ๋งŒ๋“  2018๋…„ 04์›” 09์ผ  ยท  4์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: WebAssembly/design

์–ด๋–ค ๊ฒฝ์šฐ๋ฅผ ๋งŒ๋‚ฉ๋‹ˆ๋‹ค.

ํ•˜๋‚˜๋Š” ์ ‘์ฐฉ์ œ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

int addThree(uint8_t *buf, int len) {
  uint8_t *item;
  uint8_t *end = buf + len;

  for (item = buf; item<end; item++) {
    *item += 3;
  }

  return 0;
}

๊ทธ๋Ÿฌ๋‚˜ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ .wasm ํŒŒ์ผ๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

int adder (int a, int b) {
    return a + b;
}

๊ทธ๋ž˜์„œ, ๊ธ€๋ฃจ ์ฝ”๋“œ๋Š” ๋ฌด์—‡์„ํ•ฉ๋‹ˆ๊นŒ? ๋ฌธ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์œ„์˜ ์ฃผ์„์— ์„ค๋ช…๋œ ๊ธ€๋ฃจ ์ฝ”๋“œ๋Š” Emscripten์ด ์ƒ์„ฑํ•˜๋Š” JavaScript ๋กœ๋”์ž…๋‹ˆ๋‹ค. ์ฃผ์„์ด ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. JS์™€ C++ ๋ฐ์ดํ„ฐ ํ‘œํ˜„(์˜ˆ: ๋ฌธ์ž์—ด) ์‚ฌ์ด, ๊ทธ๋ฆฌ๊ณ  ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐœ์ฒด ํ‘œํ˜„(์ฆ‰, C++ ๊ฐœ์ฒด์— ๋Œ€ํ•œ JS ํ”„๋ก์‹œ ๊ฐœ์ฒด ์ƒ์„ฑ) ๊ฐ„์— ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํ•„์š”ํ•œ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์•Œ๋‹ค์‹œํ”ผ, ์˜ˆ์ œ๋กœ ์‚ฌ์šฉํ•œ ๋‘ ํ•จ์ˆ˜์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” Emscripten ๋กœ๋”๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ๋ณต์žกํ•œ ๊ธ€๋ฃจ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์€ Wasm ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด JS ํŒŒ์ผ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค(๋‘ ๋ฒˆ์งธ ์˜ˆ์—์„œ addThree์˜ wasm ํŒŒ์ผ์€ Uint8Array๋„ ์ƒ์„ฑํ•ด์•ผ ํ•จ).

๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์€ musl์˜ malloc ๋ณต์‚ฌ๋ณธ์„ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” Wasm ์ฝ”๋“œ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” ์ž‘์—…์„ ๋งˆ์นœ ํ›„ C/C++ ์ฝ”๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•จ์œผ๋กœ์จ ํ‘œ์ค€ ๋ฐฉ์‹์œผ๋กœ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Wasm์ด ์š”๊ตฌํ•˜๋Š” ํŠน๋ณ„ํ•œ ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

๊ถ๊ทน์ ์œผ๋กœ ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฒฝ๊ณ„ ๊ฐ„ ํ˜ธ์ถœ(JS์—์„œ C++๋กœ, C++์—์„œ JS๋กœ)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ๊ธ€๋ฃจ ์ฝ”๋“œ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. WebAssembly ๋””์ž์ธ ์ž์ฒด์˜ ๋ฒ„๊ทธ๋ผ๊ธฐ๋ณด๋‹ค๋Š” Emscripten์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  4 ๋Œ“๊ธ€

๋ฌด์Šจ ๊ธ€๋ฃจ ์ฝ”๋“œ? ์ผ๋ถ€ Wasm ํŠœํ† ๋ฆฌ์–ผ์—์„œ ๋‘ ๊ฐ€์ง€ ๊ธฐ๋Šฅ( addThree() ๋ฐ adder() )์„ ๋ณต์‚ฌํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์‹ค์ œ๋กœ ๋งŽ์€ ์ผ์„ ํ•˜์ง€ ์•Š๋Š” ๋‹จ์ˆœํ•œ ์˜ˆ์‹œ ํ•จ์ˆ˜๋กœ ๋ณด์ด๋ฉฐ, ๋‹จ์ˆœํ•œ Wasm ํŠœํ† ๋ฆฌ์–ผ์„ ๋ณด์—ฌ์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ•จ์ˆ˜ ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ๋ณต์žกํ•œ ์„œ๋ช…์„ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š์œผ๋ฉฐ ๊ธ€๋ฃจ ์ฝ”๋“œ ์—†์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ๊ทธ๊ฒƒ์€ ๋‚ด ์š”์ ์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ผ๋ถ€ ๋ฌธ์„œ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์žฅ๊ธฐ์ ์œผ๋กœ ์œ ํ˜•์ด ์ง€์ •๋œ ๊ฐœ์ฒด์™€ GC๊ฐ€ ์žˆ๋Š” wasm์ด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒŒ ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ๊ฑด๊ฐ€์š”?
๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋‹จ๊ธฐ ๋˜๋Š” ์ค‘๊ธฐ์ ์œผ๋กœ ๊ทธ ๊ธ€๋ฃจ ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. C/C++๋ฅผ JS์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ๋งŒ๋“œ๋Š” ์‰˜์„ ํ˜•์„ฑํ•˜๋ ค๋ฉด ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธ€๋ฃจ ์ฝ”๋“œ์—๋Š” C ๋ฌธ์ž์—ด์„ JS ๋ฌธ์ž์—ด๋กœ ๋˜๋Š” ๊ทธ ๋ฐ˜๋Œ€๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. C++ ์ˆ˜์ค€์—์„œ JS์—์„œ C++ ํด๋ž˜์Šค ํ™•์žฅ์„ ์ง€์›ํ•˜๊ณ  JS์—์„œ ๊ฐ€์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์ƒ๋‹นํ•œ ํ•ด์ปค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ JS๋ฅผ ํ†ตํ•ด wasm์—์„œ ์›น API์— ์•ก์„ธ์Šคํ•˜๋ ค๋ฉด ๋งŽ์€ ์ ‘์ฐฉ์ œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์‚ฌ๋žŒ:

Emscripten์€ ์ œ๊ณต๋œ ํ…œํ”Œ๋ฆฟ์— ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐ ๊ธฐํƒ€ ์—ฌ๋Ÿฌ ๋ฌธ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์–‘ํ•œ JavaScript "์ ‘์ฐฉ์ œ" ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ C/C++ ์ฝ”๋“œ๋ฅผ ๋งŒ๋‚˜๋ฉด wasm์„ ์ปดํŒŒ์ผํ•˜๊ณ  export.xxxFn() ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

int adder (int a, int b) {
    return a + b;
}

๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ธ€๋ฃจ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

# C/C++
int addThree(uint8_t *buf, int len) {
  uint8_t *item;
  uint8_t *end = buf + len;

  for (item = buf; item<end; item++) {
    *item += 3;
  }

  return 0;
}

# deal with buffer in JS
...
let dataHeap = new Uint8Array(Module.HEAPU8.buffer, dataPtr, nDataBytes);
dataHeap.set(new Uint8Array(buffer_pcm.buffer));
...

๋”ฐ๋ผ์„œ Buffer๋ฅผ WASM์œผ๋กœ ์ „์†กํ•  ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐ ๊ธฐํƒ€ ์—ฌ๋Ÿฌ ๋ฌธ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๊ธ€๋ฃจ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒฐ๋ก ์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์œ„์˜ ์ฃผ์„์— ์„ค๋ช…๋œ ๊ธ€๋ฃจ ์ฝ”๋“œ๋Š” Emscripten์ด ์ƒ์„ฑํ•˜๋Š” JavaScript ๋กœ๋”์ž…๋‹ˆ๋‹ค. ์ฃผ์„์ด ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. JS์™€ C++ ๋ฐ์ดํ„ฐ ํ‘œํ˜„(์˜ˆ: ๋ฌธ์ž์—ด) ์‚ฌ์ด, ๊ทธ๋ฆฌ๊ณ  ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐœ์ฒด ํ‘œํ˜„(์ฆ‰, C++ ๊ฐœ์ฒด์— ๋Œ€ํ•œ JS ํ”„๋ก์‹œ ๊ฐœ์ฒด ์ƒ์„ฑ) ๊ฐ„์— ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํ•„์š”ํ•œ ํ˜•์‹ํ™”๋œ ๋ฐฐ์—ด์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์•Œ๋‹ค์‹œํ”ผ, ์˜ˆ์ œ๋กœ ์‚ฌ์šฉํ•œ ๋‘ ํ•จ์ˆ˜์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” Emscripten ๋กœ๋”๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ๋ณต์žกํ•œ ๊ธ€๋ฃจ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์€ Wasm ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด JS ํŒŒ์ผ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค(๋‘ ๋ฒˆ์งธ ์˜ˆ์—์„œ addThree์˜ wasm ํŒŒ์ผ์€ Uint8Array๋„ ์ƒ์„ฑํ•ด์•ผ ํ•จ).

๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์€ musl์˜ malloc ๋ณต์‚ฌ๋ณธ์„ ํฌํ•จํ•ด์•ผ ํ•˜๋Š” Wasm ์ฝ”๋“œ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋Š” ์ž‘์—…์„ ๋งˆ์นœ ํ›„ C/C++ ์ฝ”๋“œ์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•จ์œผ๋กœ์จ ํ‘œ์ค€ ๋ฐฉ์‹์œผ๋กœ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Wasm์ด ์š”๊ตฌํ•˜๋Š” ํŠน๋ณ„ํ•œ ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

๊ถ๊ทน์ ์œผ๋กœ ์ฝ”๋“œ๊ฐ€ ๋งŒ๋“œ๋Š” ๊ฒฝ๊ณ„ ๊ฐ„ ํ˜ธ์ถœ(JS์—์„œ C++๋กœ, C++์—์„œ JS๋กœ)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ๊ธ€๋ฃจ ์ฝ”๋“œ๋งŒ ์žˆ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. WebAssembly ๋””์ž์ธ ์ž์ฒด์˜ ๋ฒ„๊ทธ๋ผ๊ธฐ๋ณด๋‹ค๋Š” Emscripten์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋งค์šฐ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰

๊ด€๋ จ ๋ฌธ์ œ

konsoletyper picture konsoletyper  ยท  6์ฝ”๋ฉ˜ํŠธ

mfateev picture mfateev  ยท  5์ฝ”๋ฉ˜ํŠธ

cretz picture cretz  ยท  5์ฝ”๋ฉ˜ํŠธ

ghost picture ghost  ยท  7์ฝ”๋ฉ˜ํŠธ

jfbastien picture jfbastien  ยท  6์ฝ”๋ฉ˜ํŠธ