
웹 클라이언트 환경에서의 고정밀 타이머 구현 방안 연구
자바스크립트의 setInterval은 하드웨어 성능과 소프트웨어 환경에 따라 오차가 발생하며, 이 오차는 누적된다. 실험 결과, 자체 보정 로직을 사용하면 높은 정밀도를 유지할 수 있으며, Web Worker와 결합하여 타이머의 성능을 극대화할 수 있다. 최종 실험에서는 500초 동안 1.94초의 누적 지연이 발생했지만, 오차 복구율은 99.74%에 달했다.
setInterval은 하드웨어 성능과 소프트웨어 환경에 따라 반드시 오차가 발생
시간이 지날수록 그 오차가 누적되는 성질이 있음
1. 타이머 오차 발생 원인
자바스크립트는 싱글 스레드로 동작.
setInterval(() => { … }, 1000);으로 가정했을 경우
-setInterval함수는 정확히 1초 뒤에 실행 (X)
-setInterval함수는 1초 뒤에 실행할 작업을 큐에 넣음 (O)
실행할 시점에 하드웨어의 성능이나 다른 작업을 진행하고 있다면 해당 작업이 끝날 때까지setInterval의 콜백 함수는 대기를 하게 됨.
2. 실험 환경 및 시나리오
타이머의 정확도를 극한으로 테스트하기 위해 다음과 같은 고부하 환경을 설정함
- 환경: 크롬 브라우저 탭 20개 활성화 (리소스 점유 유도)
- 부하 조건: 타이머 루프 내에 300회 반복 연산의 강제 부하 로직 포함
- 측정 기준:
performance.now()를 이용한 마이크로초 단위 정밀 측정
3. 방식별 실험 및 최종 결론
3.1. 방식별 실험 결과 및 분석
3.1.1. 순수 setInterval 사용
- 결과: 1,050초 결과 시 약 1.333초의 지연 발생
- 분석: 지연이 발생해도 다음 실행 시점을 앞당기지 않으므로 오차가 그대로 다음 회차에 전이되고, 장시간 구동 시 실제 시간과 시스템 타이머 간의 오차가 큼
3.1.2. 자체 보정 로직 사용
- 방식: 다음 호출 주기 = 설정 주기 - (현재 시간 - 예상 시간)
예)
설정 주기 : 1000
현재 시간 : 1773118994114
예상 시간 : 1773118994105
지연 시간 : 9ms
계산식 : 1000 - (1773118994114 - 1773118994105) =
다음 호출 주기 결과 : 991
- 결과: 700초 동안 총 누적 지연은 0.724초였으나, 현재 오차는 0.8 미만으로 유지됨
- 분석: 루프마다 지연을 인지하고 대기 시간을 동적으로 계산하기 때문에 전체 타임라인이 시스템 시계를 끈질기게 따라잡음. (논리적 시계 구현에 가장 적합)
3.1.3. Web Worker 사용
- 방식: 메인 스레드와 분리된 별도 스레드에서 타이머 구동
- 결과: 현재 오차가 점진적으로 상승하는 경향을 보임
- 분석: Web Worker는 메인 스레드의 UI 부하로부터는 자유롭지만 워커 내부에서
setInterval을 단독으로 사용하면 역시 보정 기능이 없으므로 해당 스레드 내에서의 부하에 따른 지연 시간이 누적됨.
3.1.4. requestAnimationFrame (rAF) 사용
- 방식: 브라우저 주사율 (60Hz)에 맞춰 실행함
- 결과: 기본 오차가 크며, 프레임이 쌓일수록 오차가 증가함
- 분석: 렌더링 최적화에는 유리하지만, 백그라운드 전환 시 브라우저가 실행 주기를 강제로 제한하므로 지속적인 시간 측정 용도로는 부적합함
3.2. 최종 결론
| 방식 | 정밀도 | 백그라운드 유지 | 추천 용도 |
|---|---|---|---|
setInterval | 낮음 | 보통 | 단순 반복, 정밀도가 불필요한 작업 |
| 자체 보정 로직 | 높음 | 보통 | 일반 시계, 카운트다운, 스톱워치 |
| Web Worker | 보통 | 매우 높음 | 백그라운드 작업, 무거운 연산 병행 시 |
| rAF | 낮음 | 매우 낮음 | 애니메이션, 그래픽 업데이트 |
4. 최종 실험 (자체 보정 + Web Worker)
웹 브라우저에서 발생할 수 있는 타이머 오차를 극복하기 위해 Web Worker와 자체 보정 로직을 결합하여 성능 측정함. 총 8분 20초 (500초) 동안 실행 분석을 통해 지연 시간과 오차 보정을 검증함
점점 누적 지연 시간으로 인하여 시작 시간과 종료 시간의 전체 오차가 벌어지는 것을 방지하여 매 회차마다 오차를 보정함
(특정 회차에서 오차가 발생하더라도, 다음 실행 시점에서 오차를 보정함)
- 메인 스레드의 간섭 없이 별도 스레드에서 안정적인 타이머 동작 (독립성 확보)
- 이전 회차의 오차를 다음 회차에서 보정 (오차 전이 차단)
- 누적 지연이 발생함에도 불구하고, 전체 결과 시간을 실제 시계와 일치 시키는 보정 (높은 정밀도)
| 항목 | 결과 수치 | 비고 |
|---|---|---|
| 총 실행 시간 | 500,000ms (500초) | 약 8분 20초 테스트 진행 |
| 총 누적 지연 시간 | 1,940.9ms (1.94초) | 보정이 없을 경우 1.94초 지연 발생 |
| 최종 시점 오차 | 5.1ms | 실제 경과 시간: 500.005초 |
| 오차 복구율 | 99.74% | 누적 지연 시간 대비 복구 성공률 |
본 로직은 정확도가 생명인 타이머 등의 기능에 적용이 가능한 수준의 신뢰성을 보유하고 있음