핵심 요약
- 자바스크립트의 setTimeout(0)은 무분별한 리소스 낭비와 배터리 소모를 막기 위해 브라우저 표준상 최소 4ms 지연(clamping)되도록 설계되어 있습니다.
- 이로 인해 반복 작업 시 Node.js보다 브라우저에서 16배 이상 느려지는 문제가 발생하지만, 최신 웹에서는 scheduler.postTask나 MessageChannel 등으로 이를 극복할 수 있습니다.
- 브라우저 정책은 언제나 개발자의 편의보다 최종 사용자의 배터리와 반응성을 보호하는 것이 최우선이기 때문에 이 같은 제한이 유지되고 있습니다.
요약 자바스크립트 개발자라면 흔히 쓰는 `setTimeout(fn, 0)`이 실제로는 0ms가 아니라 최소 4ms 이상 지연되어 실행된다는 사실을 접하게 됩니다. 전 마이크로소프트 엣지(Edge) 팀 개발자이자 웹 성능 전문가인 놀란 로슨(Nolan Lawson)은 브라우저들이 왜 타이머를 강제로 지연(throttling/clamping)시키는지, 그리고 최신 웹 환경에서는 이를 어떻게 다뤄야 하는지 정리했습니다.
HTML 표준 사양에 따르면 `setTimeout`이 5회 이상 중첩 호출되면 브라우저는 최소 4ms의 강제 딜레이를 적용합니다. 이는 수많은 웹사이트가 무분별하게 타이머를 남발해 배터리를 광탈시키거나 사용자 인터랙션을 멈추게(blocking) 만드는 현상을 막기 위한 조치였습니다. 과거 레거시 엣지는 배터리 모드에서 이를 16ms로 늘렸고, 크롬의 경우 백그라운드 탭에서 최대 1초까지 지연시키기도 합니다.
저자는 순수 자바스크립트로 IndexedDB를 구현한 라이브러리 `fake-indexeddb`를 작업하던 중 심각한 성능 저하를 발견했습니다. 마이크로태스크 완료 직후이자 다음 매크로태스크 직전에 트랜잭션을 자동 커밋해야 하는데, Node.js에서는 지연 없는 `setImmediate` 덕분에 300ms 만에 끝나던 벤치마크가 브라우저 환경의 크롬에서는 `setTimeout` 4ms 제한에 걸려 무려 4.8초(약 16배 느림)나 걸렸던 것입니다.
이에 2025년 기준 브라우저에서 사용할 수 있는 다양한 대안들을 테스트했습니다.
- `MessageChannel.postMessage`: 크롬 0.05ms, 파이어폭스 0.02ms 수준으로 매우 빠름.
- `window.postMessage`: 빠르지만 페이지 내 다른 스크립트와 충돌할 위험이 있어 다소 불안정함.
- `scheduler.postTask()`: 크롬 0.00ms, 파이어폭스 0.01ms로 압도적인 성능과 깔끔한 API 제공 (사파리는 미지원).
결과적으로 최신 브라우저 환경에서는 `scheduler.postTask()`를 최우선으로 사용하고, 미지원 환경에서는 `MessageChannel` 등으로 폴백하는 것이 가장 효율적이라는 결론이 나왔습니다.
웹 성능 워킹그룹 전 공동 의장인 토드 라이프스테크에 따르면, 브라우저 성능 API 설계 시 개발자를 과도한 자원 낭비로부터 보호해야 한다는 입장과 자유롭게 측정하도록 둬야 한다는 입장이 팽팽히 맞서왔다고 합니다. 하지만 W3C 원칙상 개발자의 편의보다 최종 사용자의 기기 성능과 배터리 보호가 항상 우선되기 때문에, 구식 `setTimeout`에는 여전히 강력한 족쇄가 채워져 있는 셈입니다.
Sponsored · 광고