웹워커. 그게 뭔데 .

devstone·2024년 4월 20일
1
post-custom-banner

feat. 2022년도 진행했던 web.dev 스터디의 정리 자료를 뒤늦게 퍼블리시 하다 . .

0. 왜 이 주제를 하게됐는 지에 대한 구구절절한 설명

rust가 지원되지 않는 웹 ide에 rust 컴파일러 플러그인을 추가하게 되며 웹 IDE에서 rust를 최대한 지원하도록 컨트리뷰션 해야할 일이 있었습니다 .

실시간으로 코드를 쓰는 이벤트를 받으면서 어떻게 그 위치와 그 값과 그게 문법적으로 맞는지랑 그걸 어떻게 처리해야 하는 거지? → 이런 경우 문법을 체크하고 그 위치를 계산하고 등등의 작업을 별도의 스레도를 열어서 해야한다는 것을 알게됨!

그래서 찾아보니까 웹데브 사이트가 나왔습니다 ,,, ㅋㅋㅋ 스레드를 열 수 있는 방식이 두 가지가 있다더라구요.

1. Web worker vs Service worker

공통점

  • 둘 다 메인 스레드가 아닌 다른 스레드에서 작동
  • 그렇기 때문에 메인 스레드의 UI를 막지 않으면서 js 코드를 실행시킬 수 있음
  • window객체나 Document객체에 접근할 수 없음 → DOM과 다이렉트로 상호작용할 수 없고, browser api접근에 제약이 있음

차이점

  1. Web Worker
    • 네트워크 요청을 가로채서 푸쉬이벤트를 수신할 수 없음
    • 여러 웹 워커 생성 가능
    • 수명주기가 탭과 밀접하게 관련
  2. Service Worker
    • 서비스 워커는 fetch event와 같은 네트워크 요청을 탈취하거나 push event와 같은 Push API를 listen 할 수 있다.
    • 단일 서비스 워커가 등록된 scope 내에서 모든 활성 탭을 제어함
    • 사이트에 활성 탭이 없어도 백그라운드에서 실행 가능

사용 영역

  1. Web Worker
    • 웹 워커는 주로 UI block을 피하기 위해 무거운 연산이 소요되는 작업(AI, games, image encoding, etc)을 보조 스레드에서 실행하기 위해 사용된다.
  2. Service Worker
    • 서비스 워커는 일반적으로 네트워크 프록시 같은 역할이나 백그라운드 작업, 캐싱, 오프라인을 처리하는데 사용된다.

2. Web Worker을 사용하는 방식

어떻게 쓰는가

기본패턴

swfit와 같은 다중 스레드 언어처럼 UI에 관여할 수 있는 스레드는 메인 스레드이기 때문에 스레드 간의 관계가 Flux패턴과 유사

  • main.js
    const worker = new Worker("./worker.js");
    worker.postMessage([40, 2]);
    worker.addEventListener("message", event => {
      console.log(event.data);
    });
  • worker.js
    addEventListener("message", event => {
      const [a, b] = event.data;
      // Do stuff with the message
      postMessage(a+b);
    });

webpack5

이 아티클에는 2019년도 기준이라 webpack, rollup 등의 도구들이 즉시 지원하지 않는다고 쓰여있는데 현재 webpack5에서는 굉장히 예쁘고 간결한 방식으로 쓸 수 있게 지원하고 있어요!

  • main.js
    const worker = new Worker(new URL('./worker.js', import.meta.url));
    worker.postMessage({
      question:
        'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
    });
    worker.onmessage = ({ data: { answer } }) => {
      console.log(answer);
    };
  • worker.js
    self.onmessage = ({ data: { question } }) => {
      self.postMessage({
        answer: 42,
      });
    };

근데 이 방식은 webpack5에서 지원하는 방식이라 webpack4 버전 이하에서는 다른 방식들을 사용해야 한다더라구요 .. 자세한 내용은 여기에 ..

생각보다 저런 모듈 번들러 시스템에서 지원한 지 얼마되지 않았….더라구요

이건 구글 크롬팀에서 만든 라이브러리인데 편하게 웹 작업자를 사용할 수 있도록 한다고 해요. 이 라이브러리를 사용하면 특징에 다른 멀티스레드 언어처럼 웹 작업자랑 메인스레드 간에 변수를 공유할 수 있도록 기능을 제공해준다고 해요.

  • worker.js
    import {expose} from "comlink";
    
    const api = {
      someMethod() { /* … */ }
    }
    expose(api);
  • main.js
    import {wrap} from "comlink";
    
    const worker = new Worker("./worker.js");
    const api = wrap(worker);

그런데 사실 이게 단지 에디터 개발에만 쓰이는 것은 아닐테고(좀 너무 특수한 케이스니까..) 이 메인 스레드 외의 웹 워커로 스레드를 돌리는 케이스가 어떤 것이 있을까 왜 이걸 쓰게되었을까..

OMT (off-main-thread) architecture

OMT 아키텍처의 의미

Chrome Dev Summit 에서 다룬 PROXX 사례에 따르면 …

  • 도입 배경
    • 극단적으로 제한된 장치에서 해당 웹앱을 빠르게 로드하기 위한 전략
  • 의미
    • 더 넓은 범위의 기기에서 안정적으로 실행되도록 → 무조건 속도가 빨라지지는 않는다
    • 작업을 줄이는 것이 아니라 메인 스레드에서 작업을 옮기는 것이기 때문에 추가 통신 오버헤드로 인해 때때로 작업이 약간 느려질 수도 있다
      • risk reduction에 집중
      • 총 대기시간이 조금 길어질 수 있더라도 메인스레드가 blocking되지 않기 때문에 상호작용을 자유롭게 처리할 수 있다

결론적으로 목표

  • 장치 전반의 성능을 예측할 수 없기 때문에 OMT 아키텍처의 목표는 실제로 위험을 줄이는 것. 즉, 병렬화의 성능 이점이 아니라 매우 가변적인 런타임 조건에 직면하여 앱을 더욱 강력하게 만드는 것이다. 탄력성의 증가와 UX의 개선은 속도의 작은 절충보다 가치가 있다.

다만 이제..

한 스레드에서 다른 스레드로 데이터를 옮기는 시간이 오브젝트의 복잡도에 따름 ..

10kb보다 더 큰 개체를 복사하는 경우 ArrayBuffer 또는 WebAssembly 사용을 고려하면 좋다고 함!

추가적인 이점과 그래서 언제 이걸 쓸까

추가적인 이점

Web worker가 필요한 영역

도대체 어느 시점부터 웹워커가 필요한 것일까 ,,

사실상 이런 병렬처리를 고려할 때 일차적으로는 비동기적인 처리를 고려할텐데 ,,

일단 처음부터 도임하는 경우 아래 정도의 경우들로 정리할 수 있을 것 같다

  • 첫화면 동작에 영향을 미치는 연산 동작, 즉, 바이너리 파일 핸들링이나 복잡한 계산이 필요한 경우
  • 백그라운드에서 지속적인 작업을 해야 하거나 메인 스레드 영향을 미치지 않고 작업을 하는 경우
  • 멀티 스레드로 개발했을 때 사용자 환경 개선에 도움이 되는 경우.

사실상 그 외의 경우에는 개발하다보니 생기는 메인스레드 UI 병목현상을 해결하기 위해 도입하지 않을까 .. 하는 생각이 들었습니다.

https://chalu.github.io/comlink-workers/src/

잘 정리된 용례 ..

https://tech.kakao.com/2021/09/02/web-worker/

https://fe-developers.kakaoent.com/2022/220324-web-worker-image/

참고 Site

https://web.dev/workers-overview/

https://web.dev/off-main-thread/

https://web.dev/rail/

profile
개발하는 돌멩이
post-custom-banner

0개의 댓글