- 프로젝트: tracking map(유동인구분석 지도)
- 키워드: web worker, setTimeout, inactive tabs
- 상황
- setTimeout으로 특정 delay 시간 이후 동작해야하는 코드가 있다.
- 탭을 유지할 때는 버그가 일어나지 않지만, 다른 탭으로 이동(현재 탭은 비활성화)했다가 돌아오면 원하는 타이밍보다 훨씬 늦게 setTimeout이 실행되는 버그가 있다.
- 해결방법
- setTimout이 의도와 다르게 동작하는 것은 브라우저의 정책 때문이다.
https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
부하를 줄이기 위해서 탭이 inactive 될 때 delay 시간을 강제로 늘린다.
Firefox Desktop and Chrome both have a minimum timeout of 1 second for inactive tabs. - 이 문제를 해결하기 위해 'Web Worker'를 사용해보기로 한다. web worker는 독립된 thread에서 스크립트를 실행하기 때문에, inactive tab에서도 setTimeout이 원하는 타이밍에 동작한다.
- 아래는 setTimeout을 이용한 기존 로직이다. delay 시간 후 함수를 실행하고자 한다.
// example.tsx useEffect(() => { const listener = setTimeout(() => { ...함수 실행... }, delay); return () => { clearTimeout(listener); }; , [...]);
- setTimeout을 대신 실행해 줄 worker script를 작성한다.
delay를 parameter(e.data)로 받고, delay 시간 후 다시 'main script'(worker를 호출한 스크립트)에게 Message를 보내서(postMessage) setTimeout이 동작했음을 알린다.// workers/setTimeout.js onmessage = function (e) { let delay = e.data; let timer = setTimeout(() => { postMessage(null); clearTimeout(timer); }, delay); };
- 이제 이 워커를 main script에 적용한다. 아래는 웹워커를 적용한 코드이다.
// example.tsx useEffect(() => { const myWorker = new Worker('workers/setTimeout.js'); myWorker.postMessage(delay); myWorker.onmessage = function () { ...함수 실행... }; return () => { myWorker.terminate(); }; }, []);
- 이제 탭을 이동한 후 돌아와도 setTimeout이 정상적으로 작동해있다!
- setTimout이 의도와 다르게 동작하는 것은 브라우저의 정책 때문이다.
- known issues
- setTimeout 특성상 1ms 단위까지 원하는 타이밍에 동작하지는 않겠지만, 서비스에서 기대하는 수준의 동작을 구현했다.
- worker는 setTimeout만 실행시키고 메인 로직(함수)은 main script에서 실행하는 이유는 해당 함수가 DOM 조작과 관련있기 때문이다.
'프론트엔드' 카테고리의 다른 글
package.json에서 yarn resolutions 적용하기 (0) | 2022.05.21 |
---|---|
safari, iPhone 예외 상황 대응하기(Navigation Gestures, new Date) (0) | 2022.04.21 |
Hammer.js로 swipe 이벤트 감지하기 (0) | 2022.04.02 |
모바일 기기에서 scroll 관련 버그 대응하기 (0) | 2022.04.02 |
Storybook에서 user interactions 테스트하기 (2) | 2022.03.15 |