Web Workers API, OffscreenCanvas ํ์ต๋ ธํธ
- ๋ฅ์ง
- Development
- ๋ถ๋ฅ
- Javascript
- ๋ฑ๋ก์ผ
๋์ ๊ณต๊ฐ์ ๋ถ๋ฆฌ์์ผ ๋ถํ๋ฅผ ์ค์ด๋ ์ญํ ์ ํ ์ ์๋๋ณด๋ค.
ํ์ฉํ ์ ์๋ ๋ถ์ผ๊ฐ ๋ง์์ ํ์ต์ด ํ์ํ์ฌ ๋
ธํธ๋ฅผ ์์ฑํ๋ฉด์ ์ฐ๊ตฌ๋ฅผ ์์ํ๋ค.
์ฐธ๊ณ ๋งํฌ
- docs: mdn web docs
- youtube video: https://www.youtube.com/watch?v=6stSvXYwnjU
- Web Worker ๊ฐ๋จ ์ ๋ฆฌํ๊ธฐ
vite์์ worker.js ํ์ผ ์ฌ์ฉํ๊ธฐ
์ผ๋ฐ์ ์ธ ํ์ผ์ ๋ถ๋ฌ์ค๋๊ฑฐ๋ ๊ฐ์์ vite๊ฐ์ ํธ๋์คํ์ผ๋ง์ ์ฌ์ฉํ๋ ํ๊ฒฝ์์ ๋ถ๋ฌ์ค๋ฉด public๋๋ ํ ๋ฆฌ์๋ค worker.js ํ์ผ์ ๋ฃ๊ณ ์ฌ์ฉํด์ผํ๋ค.
ํ์ง๋ง ๊ด๋ฆฌ์ ์ข์ ๋ชจ์ต์ ์๋๋ผ์ src ๊ฒฝ๋ก์๋ค ๋ฃ๊ณ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฌ์ฌ ์ ์๋ค.
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' })
๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํด๋ณด๊ธฐ
๊ธฐ์ด์ ์ผ๋ก ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๋ชจ์ต์ ๋ค์๊ณผ ๊ฐ๋ค.worker.jsํ์ผ์์ ์ด์ฌํ ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ์์ง๋ฅผ ๋๊ฒจ์ฃผ๋ฉด ๋ ๋ฏํ๋ค.
// main.js
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' })
console.group('main.js')
console.log('์์')
console.groupEnd()
worker.postMessage([ 1, 2 ])
worker.onmessage = function(e)
{
console.group('main.js')
console.log('๋ฉ์ธํ์ผ์์ ๋ฉ์์ง๋ฅผ ๋ฐ๋๋ค.')
console.log('data:', e.data)
console.groupEnd()
}
// worker.js
self.onmessage = function(e)
{
console.group('worker.js')
console.log('๋ฉ์ธ์์ ๋ฉ์์ง๋ฅผ ๋ฐ์๋ค.')
postMessage({
message: '๋ฉ์ธ์ผ๋ก ๋ฉ์์ง๋ฅผ ๋ณด๋
๋๋ค.',
data: e.data[0] * e.data[1],
})
console.log('222')
console.groupEnd()
}
worker.js ์์ญ์์ ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ๊ฒฐ๊ณผ๋ฌผ์ postMessage๋ฉ์๋๋ก ๋ณด๋ด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค.worker.js ๋ด๋ถ ๋ฉ์๋์์ self๊ฐ์ผ๋ก WorkerGlobalScope์ ์ ๊ทผํ ์ ์๋ค.
๋ฉ์ง์๋ฅผ ์ ๋ฌํ์ฌ ๋ฉ์ธ๊ณผ ์์ปค ์ฐ๋ ๋ ์์ญ์ ๊ฐ์ ์ ๋ฌํ ์ ์๊ณ , ํจ์๋ฅผ ์ ๋ฌํ๋ คํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์๋๋ค.
ํ์ฉ์ฒ
๋ฉ์ธ ์ฐ๋ ๋์ ์ํฅ์ ์ฃผ์ง์๋๋ฐ ์ฌ์ฉ๋๋์ชฝ์ผ๋ก ์๊ฐํ๋ฉด ๋ ๊ฑฐ๊ฐ์๋ฐ.. ํ์ฉ์ ๋ํ์ฌ ์ข ์๊ฐํด๋ณผ ํ์๊ฐ ์๋ค.
- ๋คํธ์ํฌ ํต์
- ๋ก์ปฌ ์คํ ๋ฆฌ์ง, ์ธ๋ฑ์คdb ์ฒ๋ฆฌ
- ํ์ผ ์์คํ ์ ์ถ๋ ฅ
- ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ค๋ซ๋์ ์์ ํด์ผํ๋ ๊ฒฝ์ฐ
- UI ์๋์ ๋ฐฉํด์์ด ์์ ์ ํด์ผํ ๋
- ์น์์ผ ์ฒ๋ฆฌ
- ์ด๋ฏธ์ง ๋ก๋ฉ (Image ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ์ด๋ฏธ์ง ๋ก๋ฉ ์ํ, ์ฑ๊ณต, ์คํจ ์ฌ๋ถ๋ฅผ UI์ ๋์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์๋ค.)
์ ์ฝ
worker.js์์ญ์ ๋ง๋ฅ์ด ์๋๊ณ ์ ์ฝ์ด ์ด๋์ ๋์ธ์ง ์๊ณ ์๋๊ฒ์ด ์ข์๊ฑฐ๊ฐ๋ค.
- dom ์ปจํธ๋กค ๊ด๋ จ๋์ชฝ์ ์ฌ์ฉํ ์ ์๋ค. (
new Image๊ฐ์๊ฑธ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด๋ค.) - ๋ฉ๋ชจ๋ฆฌ ๊ณต์ ํ์ง ์๋๋ค. (๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ๊ณต์ ๊ฐ๋ฅํ์ง๋ง ์ถ์ฒ์ ์ํ๋ค๊ณ ..)
๋ง์น node.js ์์ญ๊ฐ์ ์ธ์์ด๋ค.
structuredClone()
์นจ๊ณ ๋งํฌ
๋ฐ์ดํฐ ์ ๋ฌ์ ์ํ์ฌ ๊น์๋ณต์ฌ ํจ์์ธ๋ฐ JSON.stringfy() ๋ก ์ฝ์ง์ ์ํด๋ ๋๋ ํจ์๋ค.
OffscreenCanvas
๋ค๋ฅธ ์ฐ๋ ๋์์ canvas ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋๋ฏํ๋ฐ.. ์ด๋ฏธ์ง ๋ฆฌ์ฌ์ด์ฆ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๋ ์ฌ์ฉํ ์ ์์๊ฑฐ ๊ฐ๋ค.
์ ๊น ๋ฐ๋ชจ๋ฅผ ์์ฑํด๋ณด๋ ๋ฉ์ธ์์ ์์ปค๋ก ์บ๋ฒ์ค ๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ฃผ๊ณ ์น ์์ปค ๋ด๋ถ์์ ์บ๋ฒ์ค ๊ฐ์ฒด ์ง์ ์ปจํธ๋กคํ ์ ์์๋ค. ์ด์ ๋๋ง ํด๋ ์ ๋ง๋ก ๊ฐ์ฌํ ์ผ์ธ๋ฏํ๋ค. ใ
ใท~
๋ค์์ ํ์ธ์ ์ํ ๋ฐ๋ชจ์ฝ๋๋ค.
// main.js
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' })
const canvas = document.createElement('canvas')
const offScreenCanvas = canvas.transferControlToOffscreen()
worker.postMessage({
canvas: offScreenCanvas,
src: 'image.jpg',
}, [ offScreenCanvas ])
document.body.appendChild(canvas)
// worker.js
addEventListener('message', async function(e) {
const { canvas, src } = e.data
const context = canvas.getContext('2d')
let image = await fetch(src)
image = await image.blob()
const bitmap = await createImageBitmap(image)
canvas.width = bitmap.width
canvas.height = bitmap.height
context.drawImage(bitmap, 0, 0)
})
์ฐธ๊ณ ๋งํฌ
vite์์ ๋น๋ํ ๋ inline์ผ๋ก ๋ฉ์ธ ์คํฌ๋ฆฝํธ ์ฝ๋์ ํฌํจ์ํค๊ธฐ
๊ธฐ๋ณธ์ ์ผ๋ก ์น ์์ปค์ ํ์ผ์ ๋ณ๋๋ก ๋ถ๋ฌ์์ ์ฌ์ฉํ๋ค. ํ์ง๋ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํํ๋ก ๋ฐฐํฌํ ๋ ์ ๋งํ๋ฉด ํ๋์ ํ์ผ๋ก ํฉ์ณ์ ๋ฐฐํฌํ๋๊ฒ์ด ์ข์์ ์ด ๋ง๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์น ์์ปค์ฉ์ผ๋ก ์์ ํ๊ณ ๋น๋ํด๋ณด๋ worker ํ์ผ์ด ๋ฐ๋ก ๋ง๋ค์ด์ก๋ค.
๊ทธ๋์ ์ข ์ฐพ์๋ณด๋ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์์ปค๋ฅผ ๋ถ๋ฌ์ค๋ ์์ปค ์ฝ๋๊ฐ uri ์ธ์ฝ๋ฉ์ ํ์ฌ ๋ฌธ์๋ก ๋ฐ๊ฟ๋ฒ๋ ธ๋ค.
import MyWorker from './worker.js?worker&inline'
const worker = new ImageResizeWorker()
์ ์์ ์ธ ๋ฐฉ๋ฒ์ด ์๋๊ฑฐ ๊ฐ์ง๋ง ์ ์๋ํ๋ค.;;
์ฐธ๊ณ : https://vitejs.dev/guide/assets#importing-script-as-a-worker
1๊ฐ์ ๋๊ธ
OffscreenCanvas๋ถ๋ถ์ ์ดํด๋ณผ๋ ๊ณผ๊ฑฐ์ canvas ์ฌ์ฉ์์ ํผํฌ๋จผ์ค ์ด์๋ฌ๋๊ฒ๋ค์ด ์๊ฐ๋ฌ๋ค.์ด๊ฑธ ์ฌ์ฉํ์ผ๋ฉด ๋ง์ด ๋์๋์ํ ๋ฐ.. ๋ผ๋ ์๊ฐ์ด ์ข ๋ง์ด ๋ค์๋ค. ใ ใ