본문 바로가기
개발

정확하고 효율적인 자바스크립트 타이머 구현 방법 안내

by new-fp 2024. 11. 12.
728x90
반응형

자바스크립트로 정확한 타이머 만들기: 오차 줄이기와 Web Worker 활용법

안녕하세요, 여러분! 오늘은 자바스크립트를 통해 보다 정확한 타이머를 만드는 방법에 대해 알아보겠습니다. 타이머는 웹 애플리케이션에서 자주 사용되므로, 어떻게 하면 오차를 줄이고 효율적으로 동작할 수 있도록 할 수 있는지 알아보는 것은 매우 중요합니다. 특히 웹 게임이나 애니메이션, 그리고 여러 환경에서 동작하는 타이머 어플리케이션에서 유용합니다.

자바스크립트의 기본 타이머 메커니즘

자바스크립트에서 타이머를 구현할 때 주로 사용하는 함수는 setInterval()setTimeout()입니다. 하지만 이 함수들이 정확하지 않은 이유와 그 해결책에 대해 먼저 살펴보겠습니다.


1. setInterval()setTimeout()의 한계

이 두 함수는 웹 브라우저 환경에서 특정 시간 간격으로 코드를 실행할 수 있게 도와주지만, 정확도가 떨어지는 경우가 많습니다. 왜 그럴까요?

자바스크립트는 단일 스레드에서 실행되기 때문에, 여러 작업이 동시에 발생하는 경우 이벤트 루프(Event Loop)가 이를 관리합니다. 이로 인해 타이머의 동작 시간이 정확히 설정된 인터벌에 맞춰 실행되지 않을 수 있습니다. 예를 들어, 아래 코드는 1초마다 "hello"라는 메시지를 출력하는 단순한 타이머입니다.

const INTERVAL = 1000; // 1초 간격

function timerFunction() {
    console.log('hello');
    setTimeout(timerFunction, INTERVAL);
}

setTimeout(timerFunction, INTERVAL);

이 코드에서 1초 간격으로 타이머를 설정했지만, 실제로는 각 실행 간격이 1000ms에 정확히 맞지 않는다는 것을 확인할 수 있습니다.


2. 오차 보정 방법

그렇다면 이러한 오차를 어떻게 줄일 수 있을까요? 한 가지 방법은 시간 차이를 측정하여 설정하는 것입니다. 예를 들어, 다음 시간 실행을 위한 예상 시간과 실제 실행 시간의 차이를 이용해 다음 타이머의 간격을 조정하는 것입니다.

아래 코드에서는 시간 차이를 측정하여 오차를 줄여 나가는 방법을 구현해 보겠습니다.

const INTERVAL = 1000; // 1초 간격
let expectedTime = Date.now() + INTERVAL; // 다음 실행 예상 시간

function timerFunction() {
    const drift = Date.now() - expectedTime; // 오차 계산
    expectedTime += INTERVAL;
    
    console.log(`경과 시간: ${Date.now() - startTime}ms, 오차: ${drift}ms`);
    setTimeout(timerFunction, Math.max(0, INTERVAL - drift));  // 타이머 보정
}

setTimeout(timerFunction, INTERVAL);

이 코드에서는 drift 변수를 사용해 오차를 저장하고, 다음 실행 간격을 조정하여 타이머의 정확성을 높입니다.


3. Web Worker 활용하기

앞서 언급한 방법으로는 여전히 문제점이 남아 있습니다. 브라우저 탭을 전환하거나 다른 작업을 수행할 경우 타이머의 속도가 느려지기 때문입니다. 이런 상황에서 Web Worker를 사용해서 독립적으로 백그라운드에서 코드를 실행할 수 있습니다.

Web Worker를 사용하면 메인 스레드와 관계없이 일정한 간격으로 타이머를 실행할 수 있습니다. 다음은 Web Worker를 활용한 타이머 구현 예시입니다.

1. Web Worker 파일 생성 (worker.js)

self.onmessage = function (e) {
    const INTERVAL = e.data.interval;
    let expectedTime = Date.now() + INTERVAL;

    function timerFunction() {
        const now = Date.now();
        const drift = now - expectedTime;
        expectedTime += INTERVAL;

        self.postMessage({ drift, time: now });
        setTimeout(timerFunction, Math.max(0, INTERVAL - drift));
    }

    setTimeout(timerFunction, INTERVAL);
};

2. 메인 스레드에서 Web Worker 호출

const worker = new Worker('worker.js');

worker.postMessage({ interval: 1000 }); // 1초 간격으로 타이머 실행

worker.onmessage = function (e) {
    const { drift, time } = e.data;
    console.log(`경과 시간: ${time - performance.timing.navigationStart}ms, 오차: ${drift}ms`);
};

이렇게 하면 메인 스레드에서 타이머가 독립적으로 작동하여, 다른 작업이나 탭 전환의 영향을 받지 않게 됩니다.


마무리하며

이번 포스트에서는 자바스크립트를 통해 효율적이고 정확한 타이머를 만드는 방법에 대해 알아보았습니다. 웹 애플리케이션에 타이머 기능이 필요한 경우, 본 포스트에서 소개한 방법들을 활용해 안정적인 성능을 낼 수 있을 것입니다.

프로그래밍이란 복잡한 문제를 해결하는 방안들을 찾는 것이며, 여러분이 원하는 최적의 솔루션을 개발해 보세요! 질문이 있으시면 언제든지 남겨주세요.

그럼 다음 포스트에서 만나요!

728x90
반응형