https://qshop.ai/
안녕하세요! 저는 Web Builder를 만드는 프론트엔드 개발자입니다. 본 글은 현업 프로젝트를 위한 개인적인 사전 조사입니다. web worker의 정의와 사용법에 대해서 알게되실 수 있습니다. 보고서 형식으로 작성되어 좀 재미가 없으실 수도 있습니다.
1. web worker를 공부하기로 한 배경
다른 버전에서는 drag & drop이 잘 작동하나 window7 에서는 조금 버벅이는 문제가 있었습니다. 사진에서는 크게 체감되지는 않지만, 약간 느린 감이 있습니다. 앞으로 사용자가 많아질 것이니, drag & drop 에 대한 성능 개선의 일환으로 web worker를 공부하는 것이 어떨까 했습니다.
이미지를 업로드 하거나 데이터 저장 복원 등 메인 스레드를 많이 잡아먹는 곳에서 사용할 수도 있겠습니다. 미리 공부해서 필요할 때 건의하여 사용할 수 있게 합니다.
2. 웹 워커란 것에 대해서 살펴보기
23년 11월 기준 MDN에서의 정의입니다.
Web Worker라는 것을 살펴보기 전에 브라우저의 메인스레드에 대해서 알면 더욱 좋을 것 같습니다.
메인 스레드(main thread) 는 브라우저가 사용자 이벤트와 페인트를 처리하는 곳입니다. 기본적으로, 브라우저는 단일 스레드를 사용하여 페이지의 모든 JavaScript를 실행하고 레이아웃, 리플로우 및 가비지 컬렉션을 수행합니다. 오래 실행되는 JavaScript 함수가 스레드를 차단하여 페이지가 응답하지 않고, 사용자 경험이 저하될 수 있다는 것을 의미합니다.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
여기서 중요한 것은, 브라우저의 렌더링 과정은 모두 “싱글 스레드”에서 발생된다는 것입니다. 무거운 이벤트나 실행이 오래걸리는 함수(ex On2의 반복문)들은 메인스레드에서 실행시키기 부담스럽습니다.
웹 워커를 사용하면 웹 애플리케이션의 메인 실행 스레드와 분리된 백그라운드 스레드에서 스크립트 작업을 실행할 수 있습니다. 이 경우 힘든 처리를 별도의 스레드에서 수행할 수 있으므로 메인(보통 UI) 스레드가 차단되거나 속도가 느려지지 않고 실행될 수 있다는 장점이 있습니다.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
3. 실습 및 결과보기
자세한 코드는 https://github.com/keinn51/prac_web_worker 이 곳에 있습니다. 이 글에는 버튼 태그와 css 등은 다루지 않습니다. 웹 워커가 가져올 수 있는 성능상의 이점을 중심으로 확인합니다.
- 메인 스레드로 돌리기
<script>
const eatMainThreadMem = () => {
const array = [];
for (let i = 0; i < 25000; i++) {
array.push(new Array(25000));
}
};
</script>
script tag 내부에서 함수를 실행하여, 메인스레드를 그대로 사용하는 코드입니다. eatMainThreadMem 함수는 25000번의 반복문을 돌고 있습니다. 이 함수를 main thread work
라는 글자가 있는 버튼을 눌렀을 때 실행되도록 설정합니다.
버튼을 눌렀을 때 메인 스레드가 작동합니다. 25,000번의 반복문을 처리하느라, 2506MB
만큼이나 메인 스레드를 잡아먹고 있는 것이 보입니다. (개발자 도구 참고)
메인 스레드를 활용해서 화면을 그려야 하는데, 메인스레드에 과부하가 걸려 애니메이션도 중간에 한 번 멈춥니다.
- 웹 워커를 통해 서브 스레드 활용하기
<script>
const eatMemoryWorker = new Worker("eatMemoryWorker.js");
const eatSubThreadMem = () => eatMemoryWorker.postMessage(null);
</script>
// eatMemoryWorker.js
onmessage = function (event) {
const array = [];
for (let i = 0; i < 25000; i++) {
array.push(new Array(25000));
}
};
eatMemoryWorker.js
라는 파일 내부에 worker 내부에서 사용할 onmessage 메서드를 정의해줍니다. web worker 에서는 이렇게 파일로 지정한 모듈을 가져와서, 새로운 web worker 인스턴스를 만들어주어야 한다고 합니다. (왜 그런지는 잘 모르겠습니다)
onmessage는 단어 뜻 그대로 메시지를 수신하는 메서드입니다. eatSubThreadMem
함수에서 post message를 해주면 이를 탐지해서 작동할 것입니다. eatSubThreadMem
함수를 worker thread work
라는 글자가 있는 버튼의 클릭 이벤트에 달아줍니다.
웹 워커를 사용하면 서브 스레드에는 부하가 많이 걸리지만 애니메이션이 중간에 멈추지는 않습니다. 개발자 도구를 유심히 보면 메인스레드가 아니라 제가 만든 서브 스레드에서 무거운 로직이 돌아가고 있음이 보입니다.
사용법도 비교적 간단한데요. Worker 생성자로 인스턴스를 만들어 사용하면 됩니다. 사용법에 대해서는 MDN에 워낙 자세하게 다루고 있어서 링크 첨부하겠습니다.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
4. 그래서 어디에 사용해볼껀데?
당장 성능 개선을 진행하지는 않을 것 같습니다만, 이를 위한 준비는 언제나 해두어야 한다고 생각합니다. 여러가지 웹 요소들을 마우스로 움직일 수 있는 프로덕트인 만큼 언젠가는 성능 개선이 주요 화두로 오를 것 같습니다.
사진에는 도형과 이미지 등 총 9개의 요소를 한 번에 드래그 하는 모습이 담겨 있습니다. 개발자 도구를 열어보면 50MB이던 사용량이 10초만에 150MB을 주파하고 있습니다. 웹사이트를 오래 열어두거나, 편집을 반복할 때에는 메인 스레드 사용량을 고민할 시기가 오지 않을까 합니다.
개인적인 사전 조사이지만 누군가에게 도움이 되면 더욱이 좋을 것 같습니다!!
'Develop' 카테고리의 다른 글
lazy loading으로 Entry Point File 크기 줄이는 방법 연구 (0) | 2024.07.20 |
---|---|
React context 대신 Event bus를 사용해 렌더링 개선하는 방법 조사 (0) | 2024.07.20 |
React : performamce, profiler를 통한 성능 개선 측정하기 (drag & drop, state refactoring) (0) | 2024.07.20 |
쿠키로 마음을 전하고 싶으면 도메인부터 맞추자 🍪 (0) | 2024.07.20 |
친구 프로그램 만들어주기 (with C) (0) | 2024.07.20 |