개발/js

JS - 실시간 시계 만들기 (requestAnimationFrame)

waterpole-dev 2022. 9. 6. 18:58
반응형

실시간 시계를 만들 일이 생겼었습니다.

setInterval, setTimeout, requestAnimationFrame 셋 중에

requestAnimationFrame을 통해 만들기로 결정했습니다.

 

그 이유는 전에 setInterval, setTimeout이 시간이 지남에 따라 미세하게 밀렸었던 경험이 있고, 링크에도 나와있다시피 불필요한 콜 스택이 많이 호출된다(성능 이슈). 마지막으로 찾아보다 알게 된 건데 모니터의 표시 가능한 주사율에 영향을 받는다는 점 이 때문에 requestAnimationFrame으로 구현했습니다.

 

requestAnimationFrame으로 애니메이션을 만들었을 때의 특징으로는 위에서 얘기한 콜 스택, 주사율 등등 외에

  • 백그라운드 동작 혹은 비활성화 시 중지
  • 최대 1ms 제한 = 1초당 60프레임
  • 다수의 애니메이션이 동일한 타임을 참조

등이 있습니다. 하지만, Maximum Calltack이 발생할 수 있기에 조건을 걸어주는 등 적 잘한 조치가 필요합니다.

 


현재 시간 가져오기

// current date info
function dateInfo(staticDate = new Date()) {
    const currentDate = staticDate;
    const year = currentDate.getFullYear();
    const month = currentDate.getMonth() + 1;
    const date = currentDate.getDate();
    const hour = currentDate.getHours();
    const min = currentDate.getMinutes();

    return { currentDate, year, month, date, hour, min };
}

// set real time
function setRealTime() {
    let { currentDate, year, month, date, hour, min } = dateInfo();
    const ampm = hour >= 12 ? 'PM' : 'AM';
    hour = modifyTimeUnit(hour);
    min = modifyTimeUnit(min);

    return { ampm, hour, min, date, month, year };
}

// modify time unit
function modifyTimeUnit(time) {
    if (time < 10) return '0' + time;
    return time;
}

저는 필요에 의해 dateInfo, setRealTime 함수 두 개로 나눴지만, 굳이 나눌 필요는 없습니다.

 

우선 dateInfo함수에서 년, 월, 일, 시, 분 정보를 변수에 담아 객체 형태로 리턴해준 후에

setRealTime함수에서 지금이 오전/오후인지, 그리고 한 자릿수 일 때 modifyTimeUnit 함수를 이용해서 앞에 0을 붙여 2 자릿수로 통일시켜줬습니다.

(dateInfo함수 안에 month부분에 +1을 해준 이유는 getMonth()로 달 정보를 받아오면 0~11까지 리턴해주기에 1월~12월을 맞추기 위함입니다.)

const test = setRealTime();

console.log(test)

// result
// {
//     ampm: "PM"
//     date: 6
//     hour: 18
//     min: 12
//     month: 9
//     year: 2022
// }

결과

 

 

실행하기

requestAnimationFrame을 할당할 변수를 생성 후 시작 함수를 만들어 봅시다.

let timerAF;

function startRealTime() {
    let { ampm, hour, min, date, month, year } = setRealTime();
    timerAF = requestAnimationFrame(startRealTime);

    console.log(`${year}.${month}.${date} ${ampm} ${hour}:${min}`);
}

startRealTime();

// 실행 결과
// 2022.9.6 PM 18:41
// ...

startRealTime 함수를 requestAnimationFrame(startRealTime)을 통해 재귀적으로 실행합니다.

그러면 setRealTime함수를 재호출 하면서 새로운 실시간 날짜 데이터를 생성하고, 가공된 해당 데이터를 받아와서 콘솔에 뿌려주게 됩니다.

 

const elem = document.querySelector('.currunt-time');
elem.innerText = `${year}.${month}.${date} ${ampm} ${hour}:${min}`;

콘솔 대신 이런 식으로 사용하시면 DOM에도 표시가 됩니다.

(초를 받아오고 있진 않아서 분이 변경될 때마다 text가 변할 겁니다.)

 

저런 방식을 통해 날짜 데이터에서 가져올 항목을 제거하거나 추가하여 본인의 필요에 맞게 가공 후 사용하시면 되겠습니다.

 

아 마지막으로 requestAnimationFrame(startRealTime)가 아니라 requestAnimationFrame(startRealTime())이렇게 함수를 호출해버리면 Maximum Calltack이 뜨니 주의하세요!


 

피드백 및 코멘트는 언제나 환영입니다!

감사합니다 :)

반응형