React에서 WebWorker 사용하기

웹 워커를 사용하는 환경에 놓여 이에 대하여 알아보았습니다.

사용방법에 초점을 맞춰 정리했습니다. 😊

 

자바스크립트는 싱글 스레드입니다.

데이터 처리 시간이 길게 소요되는 작업이 실행되면 해당 연산이 마무리되기 전까지 다른 이벤트를 실행하면 동작하지 않습니다.

이때 유저 입장에서는 불편함을 느낄 있는데 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 배열을 파라미터로 담아 실행시킵니다.

 

worker와 컴포넌트에서의 console.log

각각의 액션 별로 지정한 함수가 실행되어 정상적으로 결과를 컴포넌트단에서 수신할 수 있습니다.

이런 식으로 응용하여 웹 워커를 사용할 수 있습니다.

 

용도에 맞게 잘 활용한다면 유용한 Web API 인 것 같습니다.

onerror등 여러 메소드가 있으니 MDN에서 확인해보세요 !

 

참고자료

https://developer.mozilla.org/ko/docs/Web/API/Web_Workers_API/Using_web_workers

 

웹 워커 사용하기 - Web API | MDN

웹 워커는 웹 컨텐츠를 위해서 백그라운드 스레드에서 스크립트를 실행할 간편한 방법을 제공합니다. 워커 스레드는 사용자 인터페이스(UI)를 방해하지 않고 작업을 수행할 수 있습니다. 또한

developer.mozilla.org

 

'JavaScript' 카테고리의 다른 글

input type number에서 한글입력 방지  (1) 2022.06.17
ES2021 (ES12)에서 추가되는 기능들!  (0) 2021.02.15