티스토리 뷰

카테고리 없음

Web Worker

kmj24 2024. 5. 26. 16:40

- Web worker를 이해하기 위해 프로세스와 스레드에 대하여 알고 있어야 한다.

프로세스란?

  • 실행중인 프로그램이다.
  • 즉, OS로부터 메모리를 할당받아 실행중인 프로그램을 의미한다.
  • 이러한 프로세스는 프로그램에 사용되는 데이터와 메모리, 스레드(Thread) 등으로 구성된다.

스레드란?

  • 프로세스 내부에서 실행되는 작업 단위(unit)이다.
  • 하나의 프로세스는 내부에 여러개의 스레드가 포함될 수 있다.
  • 여러개의 스레드는 서로의 데이터에 접근이 가능하다.
  • 스레드도 프로세스처럼 작업을 병렬로 처리할 수 있다.
  • 스레드의 메모리 영역을 thread stack이라고 부른다.

멀티 스레드

  • 여러개의 스레드를 구성하여 작업을 병렬로 처리한다.
  • 예를 들어 1분이 소요되는 4개의 작업을 직렬로 처리할 경우 4분이 소요된다.
  • 멀티스레딩으로 4개의 작업을 병렬로 처리한다면 1분으로 처리 시간을 단축할 수 있다.

JS에서의 스레드

  • JS는 이벤트 루프라는 싱글 스레드로 동작한다.
  • 코드를 한줄한줄 차례대로 실행하며 하나의 작업에 걸리는 시간과 관계없이 이전단계의 코드가 실행된 후 다음 단계의 코드가 실행된다.
    • 하지만 JS에서 비동기 처리를 제공한다. (Promise, Async/Await)
    • 이러한 비동기처리가 가능함으로 멀티스레드처럼 동작한다.
    • 이벤트 루프와 WebAPI의 메커니즘으로 비동기 처리가 가능하여 멀티스레드처럼 보일 수 있을 뿐 싱글스레드로 동작한다.
    • 이벤트루프에 대해서 : https://kmj24.tistory.com/128

브라우저에서의 스레드

  • 브라우저는 다양한 스레드로 구성되어 있다.
  • 메인 스레드
    • 브라우저가 사용자 이벤트와 페인트를 처리하는 곳, JS가 실행되는 스레드이다.
  • 워커 스레드
    • JS를 메인 스레드와 분리된 별도의 백그라운드 스레드에서 실행할 수 있도록 한다.
    • Web worker, Service Worker 등이 있다.
  • 컴포지터 스레드
    • 웹 페이지의 레이아웃, 페인팅 작업을 처리한다.
  • 스토리지 스레드
    • 브라우저의 스토리지(local, session, cookie, indexedDB등) 브라우저 저장소에 접근하는 작업을 처리한다.
  • 네트워크 스레드
    • 네트워크 요청을 처리한다.
  • ETC..

Web worker

  • Web Worker 는 브라우저의 메인 스레드 와 별개로 작동되는 스레드이다

Web worker를 이용한 브라우저 멀티 스레딩을 사용한 예시

  • canvas를 이용하여 차트를 개발한 경험이 있다.
  • canvas는 화면에 다시 그릴 때 canvas의 영역을 전체 지우고 다시 그리는 방식으로 다시 그린다.
  • 그렇기 때문에 canvas에 인터렉티브한 요소를 사용한다면 화면을 다시 그리기 위한 전체 연산을 해야한다.
  • 인터렉티브한 요소가 작다면(다시 그릴 필요가 없는 요소가 많은) 그만큼 비효율적인 연산이 실행되는 것이다.
  • canvas에서는 이를 위해 최적화 방안이 있다.
    • 여러개의 canvas를 겹쳐두어 정적 요소에 대한 canvas, 동적 요소에 대한 canvas를 따로 그려내어 동적 요소만 다시그리도록 하는것.
    • Path2D를 사용하여 그릴 경로를 미리 정해두고, canvas에 직접적으로 무엇인가를 지시하는 횟수를 줄이는 것
    • 하지만 이 방법만으로 충분하지 않을 수 있다.
    • 브라우저는 Web Worker라는 스레드를 제공하며, 멀티스레딩을 이용한 canvas의 연산을 할 수 있다.
  • Offscreen Canvas
    • canvas를 그리기 위해 대량의 연산을 실행 할 때 메인스레드만을 이용한다면 그만큼의 지연이 발생할 것이다.
    • 이때 메인 스레드가 아닌 백그라운드 스레드에서 canvas를 다룬다면, 그만큼의 지연을 줄일수 있다.
    • OffscreenCanvas는 Main thread가 아닌 Web worker에서 렌더링하여 지연에 대응하므로 더 좋은 UX를 제공할 수 있다.
  • Offscreen Canvas 예시
    • 검은 공이 canvas 왼쪽에서 오른쪽으로 이동하는 애니메이션이 있다.
    • 이때 main thread에 강제로 부하를 걸었을 때, 일반 canvas와 offscreen canvas의 차이를 비교해 볼것이다.
    • animation
const animation = (callback: () => void) => {
	callback();
	requestAnimationFrame(animation);
}

const draw = (ctx: CanvasRenderingContext2D) => {
  let xPos = 10;

  return () => {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.beginPath();

    ctx.arc(xPos, 100, 10, 0, Math.PI * 2, false);
    ctx.fill();

    xPos += 3;
		
		// canvas의 width는 1200
    if (xPos > 1200) {
      xPos = 0;
    }
  };
};
  • 일반 canvas
const canvas = document.querySelector('.canvas');
const ctx = canvas.getContext('2d');
animation(draw(ctx));
  • offscreen canvas
    • offsecreen canvas는 canvas와 다르게 worker를 생성하여 offscreen canvas를 넘겨준다.
    • 애니메이션 렌더링은 워커에서 실행하도록 하는 것이다.
const canvas = document.querySelector('.canvas');
const offscreen = canvas.transferControlToOffscreen();

const worker = new Worker('worker.js');
worker.postMessage({ canvas: offscreen }, [offscreen]);

// worker.js
import { draw } from './draw';

const worker = self;
worker.onmessage = (e) => {
  const { canvas } = e.data;
  const ctx = canvas.getContext('2d')!;

  animation(draw(ctx));
};
  • 메인스레드의 부하
    • 3초간 main thread가 while문 내에 머물도록 한다.
// 3초간 main thread를 blocking
const blockThread = () => {
  const start = Date.now();
  while (Date.now() - start < 3000) {}
};
  • 부하가 일어나면 canvas는 렌더링을 멈춘다. 반면 worker thread에서 실행되는 offscreen canvas는 렌더링을 멈추지 않는다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함