본문 바로가기
dev/javascript

[javascript] 자바스크립트 경과시간 계산 (stopwatch)

by 최연탄 2023. 2. 6.
728x90
반응형

참고: https://ralzohairi.medium.com/displaying-dynamic-elapsed-time-in-javascript-260fa0e95049

프론트엔드 개발자로서 경과된 시간을 동적으로 표시해야할 때가 있습니다. 예를 들어 통화 인터페이스에 경과 시간을 표시해야 하거나 웹 사이트에 스톱워치 기능을 개발해야하는 경우가 있습니다. 따라서 단순히 재사용 가능한 함수가 있다면 좋을 것 입니다. 이제부터 알아보겠습니다.

이 포스트에서는 자바스크립트를 사용하여 경과시간을 계산하고 표시하는 방법을 설명합니다. 여기서 설명하는 알고리즘과 논리는 자바스크립트가 아닌 다른 프로그래밍 언어에서도 동일하게 적용할 수 있습니다.

1. 경과 시간을 계산하는 함수 구현

첫 번째 만들 구문은 시작 시간과 종료 시간 사이의 경과 시간을 계산하는 기능을 구현하는 것인데, 여기서 종료 시간은 함수가 호출되는 순간에 캡쳐된 시간입니다.

이를 위해 getElapsedTime() 함수는 다음과 같이 명세사항에 따라 구현합니다.

getElapsedTime() - mm:ss 형식이나 hh:mm:ss 형식으로 경과된 시간을 리턴
Input - 시작 시간을 나타내는 Date 객체
Output - mm:ss 형식이나 hh:mm:ss 형식으로 경과된 시간을 표시

함수가 시작되면 종료 시간을 기록할 변수를 만듭니다. 이는 다음의 코드로 구현합니다.

// 종료 시간 기록
let endTime = new Date();

이 다음 시작 시간과 종료 시간 사이의 시간 차이를 계산할 것 입니다. 이 작업은 두개의 Date 객체를 밀리초 단위로 변환한 다음 아래 코드처럼 시작 시간을 종료 시간에서 빼서 수행합니다.

// 밀리초 경과 시간 계산
let timeDiff = endTime.getTime() - startTime.getTime();

getTime()은 "Jan 1st, 1970 00:00:00 UTC" 부터 주어진 시간까지의 경과 밀리초를 리턴하는 빌트인 메소드 입니다. 따라서 getTime() 함수는 동일한 시작점을 기준으로 계산되므로 단순 시간 빼기 결과는 항상 정확합니다.

밀리초 단위의 시간차이를 얻으면 이를 활용해 초로 변환하여 초, 분, 시간, 일을 추출할 수 있습니다. 이 작업은 다음 코드와 같이 구해진 시간차를 1000으로 나누어 수행합니다.

// 시간차이 밀리초를 초로 변환
timeDiff = timeDiff / 1000;

1.1 초 추출

초를 추출하려면 그냥 완전한 분에 들어가지 못한 수를 구하면 됩니다. 즉 timeDiff를 60으로 나눈 나머지 값을 말합니다.

초에 해당하는 값을 얻으면 Math.floor() 메소드를 적용하여 정수 값만 추출하고 나머지 값은 무시합니다. 그 다음 숫자 타입인 초를 문자열 타입으로 바꾸고 만약 결과가 한 글자라면 앞에 0을 패딩으로 붙입니다. 다음 코드를 보겠습니다.

// 분이 되지 못한 정수 값의 초를 얻기위해 % 연산자 사용
let seconds = Math.floor(timeDiff % 60);
// 결과 값이 한 자리면 0 패딩
let secondsAsString = seconds < 10 ? "0" + seconds : seconds;

1.2 분 추출

분을 추출하려면 시간차를 초에서 분으로 변환해야 합니다. 이는 다음 코드와 같이 timeDiff를 60으로 나눈 다음 Math.floor()를 적용합니다. 이 시점에 사용하는 floor() 메소드는 분에 포함되지 못한 초를 이미 구해서 필요 없기 때문에 소수점 값을 내림하기 위함입니다.

// 초 단위의 시간차를 분 단위로 변환
timeDiff = Math.floor(timeDiff / 60);

분을 추출하기 위해, 앞서 초 추출에서 했던 것 처럼 완전한 시간이 되지 못한 분의 값이 필요합니다. 즉 분단위로 변환한 timeDiff를 60으로 나눈 나머지 값을 말합니다. 그 다음 숫자타입의 값을 문자열로 바꾸고 한자리면 0 패딩을 합니다. 이번에는 이전 단계에서 불필요한 값을 제거했기 때문에 Math.floor() 메소드가 필요 없습니다.

// 모듈러 연산으로 정수 분 구하기
let minutes = timeDiff % 60;
// 한자리면 0으로 패딩
let minutesAsString = minutes < 10 ? "0" + minutes : minutes;

1.3 시간 추출

시간을 구하기 위해서는 시간차를 분 단위에서 시간 단위로 변환해야합니다. 이는 다음의 코드처럼 timeDiff를 60으로 나눠서 얻을 수 있습니다.

// 시간차를 분 단위에서 시간 단위로 변환
timeDiff = Math.floor(timeDiff / 60);

시간을 추출하려면 앞의 초 추출, 분 추출과 마찬가지로 완전한 일(24시간)이 되지 못한 값을 구합니다. 즉 timeDiff를 24로 나눈 나머지를 구합니다.

// 모듈러 연산으로 정수형 시간 추출
let hours = timeDiff % 24;

이 시점에서 완전한 일이 되지 못한 시간을 추출했습니다. 다음 단계는 경과된 시간의 값을 시간으로 변환하고 시간 변수에 저장하는 것 입니다.

일을 추출하려면 시간차를 시간 단위에서 일 단위로 변환해야 합니다. 이 작업은 timeDiff를 24로 나눈 다음 아래 코드처럼 floor() 메소드를 적용합니다. 이 시점의 timeDiff는 일 수와 같습니다.

// 시간 단위를 일 단위로 변환
timeDiff = Math.floor(timeDiff / 24);
// timeDiff의 값은 일 수 입니다.
let days = timeDiff;

이제 총 시간 수를 계산하기 위해 일 수를 시간으로 변환하여 시간 변수에 추가합니다. 일 수를 시간으로 변환하려면 일 수에 24를 곱하면 됩니다. 그다음 시간을 문자열로 바꾸고 한자리면 0 패딩을 추가합니다.

// 남은 timeDiff는 일 수
let days = timeDiff;
let totalHours = hours + (days * 24); // 일 수 값과 시간 값을 더해 총 시간 계산
let totalHoursAsString = totalHours < 10 ? "0" + totalHours : totalHours;

1.4 경과 시간 포멧과 리턴

이제 전체 경과 시간을 계산했으므로 적절하게 포멧을 지정하고 값을 리턴할 차례입니다.

다음 코드와 같이 총 시간이 0일 경우 mm:ss 형식으로 포멧하고 아닐 경우 hh:mm:ss 형식을 리턴합니다.

if (totalHoursAsString === "00") {
	return minutesAsString + ":" + secondsAsString;
} else {
	return totalHoursAsString + ":" + minutesAsString + ":" + secondsAsString;
}

2. 경과 시간 표시 및 동적 업데이트

현재 경과 시간을 계산하는 함수를 만들었습니다. 이제 경과된 시간을 표시하고 매 초 마다 업데이트 해보도록 하겠습니다.

이를 위해 먼저 경과된 시간의 문자열 값을 가질 변수를 정의해야합니다. 이 변수는 초기값으로 경과 시간을 나타내는 값 "00:00"으로 초기화하며 초당 경과 시간을 반영하도록 업데이트됩니다.

이 변수는 경과 시간 값을 가질 HTML 요소의 innerText 속성 값이 됩니다. 다음 코드를 보겠습니다.

// 화면에 표시될 값의 초기 값 설정
let displayedElapsedTime = "00:00";

다음으로 시작 시간을 정의해야합니다. 이 값을 getElapsedTime() 함수에 매 초 마다 매개변수로 전달될 것 입니다.

// 시작 시간 설정
let startDate = new Date();

변수 값 준비는 다 마쳤습니다. 이제 JavaScript의 setInterval() 메소드를 사용하여 인터벌을 설정할 시간입니다. 이 메소드는 일정한 간격으로 매개변수로 전달된 콜백 함수를 실행합니다. 이 콜백함수는 getElapsedTime() 함수를 통해 매번 경과된 시간을 계산할 것 입니다. 다음의 코드를 보겠습니다.

// 매 초 마다 경과된 시간 계산
let elapsedTimeIntervalRef = setInterval(() => {
	displayedElapsedTime = timeAndDateHandling.getElapsedTime(startDate);
}, 1000); // 1000 밀리초는 1 초

이 setInterval() 메소드가 리턴한 참조는 필요 시 인터벌 중지를 위해 변수로 기억하고 있어야 합니다.

clearInterval(elapsedTimeIntervalRef);

stopwatch 코드

이 코드 데모는 JavaScript를 사용하여 동적 경과 시간을 표시하기 위해 설명한 것들을 구현한 stopwatch 입니다.

See the Pen stopwatch by shinyks (@shinyks) on CodePen.

관련 글

자바스크립트 Date 사용 방법

자바스크립트 반올림, 올림, 내림

자바스크립트 setInterval 사용 방법

반응형

댓글