웹 워커를 사용하는 환경에 놓여 이에 대하여 알아보았습니다.
사용방법에 초점을 맞춰 정리했습니다. 😊
자바스크립트는 싱글 스레드입니다.
데이터 처리 시간이 길게 소요되는 작업이 실행되면 해당 연산이 마무리되기 전까지 다른 이벤트를 실행하면 동작하지 않습니다.
이때 유저 입장에서는 불편함을 느낄 수 있는데 WebWorker를 이용해 백그라운드 스레드로 해당 이슈를 개선할 수 있습니다.
또한 웹 워커에서는 DOM 컨트롤을 직접적으로 할 수 없기 때문에 결과를 전달받아 사용해야 합니다.
다른 예제들에 해당 기능을 지원하는지 확인하는 코드가 있어 확인해봤는데 잘 지원되는 것 같다.
개발 중인 서비스의 지원 브라우저를 확인하고 작업하면 좋을 듯합니다!
사용 환경
1. React 17.0.2
2. vite 2.72
폴더 구조
src/utils
/workers
/component
// /workers/test.worker.js
self.onmessage = ({ data }) => {
console.log(data,'data from onmessage')
}
1. 여러 가지 워커들을 생성하기 위해 workers 폴더에 워커 파일을 생성합니다.
2. self는 워커 내부의 worker 전역 스코프에 대한 참조입니다.
3. onmessage는 수신을 받을 수 있는 메서드입니다.
4. 데이터가 넘어오는지 확인하기 위해 콘솔을 찍어봅니다.
// /utils/testWorker.js
import TestWorker from '../workers/test.worker.ts?worker'
export const testWorker = new TestWorker()
1. utils 폴더는 워커를 생성하고 호출하는 함수를 만들 것입니다.
2. vite환경에서 웹 워커를 사용할 때 경로에 ?worker를 붙여줘야합니다!
// component/Test.tsx
import React from 'react'
const Test = () => {
return (
<button
onClick={() => {
testWorker.postMessage({ hello: 'world' })
}}>
워커 테스트
</button>
)
}
export default Test
1. postMessage는 데이터를 발신하는 메서드입니다.
2. 컴포넌트단에서 데이터를 발신하기 위해 클릭 이벤트를 통해 post 하는 코드를 작성합니다.
버튼을 누르면 정상적으로 작동하는 것을 확인할 수 있습니다.
사실 웹 워커의 작동법은 이게 전부입니다.
머쓱...타드
데이터를 전달받은 곳에서 데이터 가공이나 연산 등 행위를 해주면 되는 것이죠.
그럼 위 예제를 reducer 형식으로 변형하여 간단한 예제로 적용해보겠습니다.
// /workers/test.worker.js
const arraySum = (array: number[]) => {
return array.reduce((acc,cur)=>{
return acc + cur
},0)
}
const arrayAverage = (array:number[]) =>{
return array.reduce((acc,cur)=>{
return acc + cur
},0) / array.length
}
self.onmessage = ({ data }) => {
console.log(data,'data from onmessage')
switch (data.action) {
case 'arraySum':
const sum = arraySum(data.payload)
self.postMessage({ arraySum:sum })
break;
case 'arrayAverage':
const average = arrayAverage(data.payload)
self.postMessage({ arrayAverage:average })
break;
default:
break
}
}
1. 숫자 배열을 전달받아 배열의 합과 평균을 리턴해주는 arraySum arrayAverage 함수를 작성했습니다.
2. post로 데이터를 보낼 때 action과 payload를 전달해줄 것이고 각 액션마다 작성한 함수를 실행시키고 결과를 post 해주는 switch문을 작성했습니다.
// /utils/testWorker.js
import TestWorker from '../workers/test.worker.ts?worker'
export const testWorker = new TestWorker()
export const arraySum = <T>(array: T[]) => {
testWorker.postMessage({ action: 'arraySum', payload: array })
}
export const arrayAverage = <T>(array:T[]) => {
testWorker.postMessage({action:'arrayAverage' ,payload:array})
}
1. 첫 예제에서는 postMessage를 컴포넌트단에서 직접 작성했지만 다른 곳에서도 쉽게 사용할 수 있도록 함수로 만들어 export 합니다.
2. arraySum 함수는 데이터를 받아 'arraySum'이라는 액션을 함께 워커에게 전달합니다.
3. arrayAverage 함수는 데이터를 받아 'arrayAverage'라는 액션을 함께 워커에 전달합니다.
// component/Test.tsx
import { useEffect, useState } from 'react'
import { testWorker, arraySum, arrayAverage } from '../../../utils/testWorker'
const Test = () => {
const [testArray,setTestArray] = useState([6,4,3,2,6,7])
useEffect(() => {
testWorker.onmessage = ({ data }: any) => {
console.log(data,'onmessage 컴포넌트에서 받는 메세지입니다.')
};
}, []);
return (
<button
onClick={()=> {
arraySum(testArray)
}}
>
배열 더하기
</button>
<button
onClick={() => {
arrayAverage(testArray)
}}
>
배열 평균
</button>
)
}
export default Test
1. useState에 숫자 배열을 선언했습니다.
2. Worker로부터 전달받은 값을 컴포넌트단에서 확인할 수 있게 useEffect에 onmessage 리스너를 작성했습니다.
3. utils 폴더에서 작성한 덧셈 함수와 평균 함수를 각각의 버튼에 testArray 배열을 파라미터로 담아 실행시킵니다.
각각의 액션 별로 지정한 함수가 실행되어 정상적으로 결과를 컴포넌트단에서 수신할 수 있습니다.
이런 식으로 응용하여 웹 워커를 사용할 수 있습니다.
용도에 맞게 잘 활용한다면 유용한 Web API 인 것 같습니다.
onerror등 여러 메소드가 있으니 MDN에서 확인해보세요 !
참고자료
https://developer.mozilla.org/ko/docs/Web/API/Web_Workers_API/Using_web_workers
'JavaScript' 카테고리의 다른 글
input type number에서 한글입력 방지 (1) | 2022.06.17 |
---|---|
ES2021 (ES12)에서 추가되는 기능들! (0) | 2021.02.15 |
Comment