본문 바로가기
Programming/JavaScript

[JS] D-DAY 카운트 구현

by 공부합시다홍아 2024. 6. 13.
 

[JavaScript] 날짜를 생성하는 New Date

Date 생성자는 시간의 특정 지점을 나타내는 Date 객체를 플랫폼에 종속되지 않는 형태로 생성한다.Date 객체는 1970년 1월 1일 UTC(국제표준시) 자정으로부터 지난 시간을 밀리초로 나타내는 UNIX

hong-study.tistory.com

이전 게시물을 통해 new Date 함수를 이용해, 오늘의 날짜와 D-Day를 구해볼 수 있었다.
오늘은 new Date 함수를 응용해 D-Day를 구현해보려고 한다.

설명은 위해 아래와 같이 표기

  • element : 초록색
  • method : 파랑색
  • Parameter : 주황색
  • Variable : 빨강색

HTML 구성 및 설명

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="/style.css">
    <script src="/script.js" defer></script>
</head>
<body>
    <h1>D-DAY</h1>
    <div id="d-day-container">
        <div class="d-day-child-container" >
            <span id="days">0</span>
            <span>일</span>
        </div>
        <div class="d-day-child-container" >
            <span id="hours">0</span>
            <span>시간</span>
        </div>
        <div class="d-day-child-container" >
            <span id="min">0</span>
            <span>분</span>
        </div>
        <div class="d-day-child-container">
            <span id="sec">0</span>
            <span>초</span>
        </div>
    </div>
    <div id="d-day-message"></div>
    <div id="target-selector id">
        <input type="text" id="target-year-input" class="target-input" size="5"/> 년
        <input type="text" id="target-month-input" class="target-input" size="5"/> 월
        <input type="text" id="target-date-input" class="target-input" size="5"/> 일
    </div>
    <button onclick="starter()" class="btn">카운트다운 시작</button>
    <button onclick="resetTimer()" class="btn">타이머 초기화</button>
</body>
</html>

먼저 구성으로는 제목과 표현될 기간이 담길 공간 그리고 입력할 태그 그리고 버튼으로 구성되어 있다.

Element

  • days : 남은 "일" 수가 담길 요소
  • hours : 남은 "시간"이 담길 요소
  • min : 남은 "분"이 담길 요소
  • sec : 남은 "초"가 담길 요소

Event

  • starter() : 카운트다운을 시작할 이벤트
  • resetTimer() : 진행중인 카운트 다운을 초기화할 이벤트

JavaScript

먼저 이전 new Date 함수에 대해 공부할 때 사용할 던 아이디를 그대로 사용한다.

dateFormMaker() 함수

const dateFormMaker = function () {
    const inputYear = document.querySelector("#target-year-input").value;
    const inputMonth = document.querySelector("#target-month-input").value;
    const inputDate = document.querySelector("#target-date-input").value;

    const dateFormat = `${inputYear}-${inputMonth}-${inputDate}`;

    return dateFormat;
};

dateFormMaker 함수는 "년", "월", "일"의 입력한 값을 가지고와, dateFormat 변수에 원하는 형식으로 변환해주는 역할을 하는 함수이다. 


counterMaker() 함수

const counterMaker = function (data) {

    const nowDate = new Date();
    const targetDate = new Date(data).setHours(0,0,0,0);
    const remaining = (targetDate - nowDate) / 1000;

    // reamining이 0이 된다면 현재 시간이 목표 시간에 도달
    if(remaining == 0){
        container.style.display = "none";
        msgContainer.innerHTML = "<h3>타이머가 종료되었습니다.</h3>"
        msgContainer.style.display = "flex";
        resetTimer();
        return;
    }else if(isNaN(remaining)){
        container.style.display = "none";
        msgContainer.innerHTML = "<h3>유효한 시간대가 아닙니다.</h3>"
        msgContainer.style.display = "flex";
        resetTimer();
        return;
    }else if(remaining < 0){
        container.style.display = "none";
        msgContainer.innerHTML = "<h3>날짜가 지나 확인이 불가합니다. 다시 입력해주세요</h3>"
        msgContainer.style.display = "flex";
        resetTimer();
        return;
    }

    const remainingObj = {
        remainingDate: Math.floor(remaining / 3600 / 24),
        remainingHours: Math.floor(remaining / 3600) % 24,
        remainingMin: Math.floor(remaining / 60) % 60,
        remainingSec: Math.floor(remaining) % 60,
    };


    const documentArr = ['days', 'hours', 'min', 'sec'];
    const timeKeys = Object.keys(remainingObj);

    const format = function(time) {
        if(time < 10){
            return "0" + time;
        }else{
            return time;
        }
    }

    var i = 0;
    for(var tag of documentArr){
        const remainingTime = format(remainingObj[timeKeys[i]]);
        document.getElementById(tag).textContent = remainingTime;
        i++;
    }

};

counterMaker 함수는 D-day 계산을 위해 사용하는 함수로, 목표 날짜(targetDate)와 현재 날짜(new Date) 간의 차이인
밀리초 단위의 차이를 일, 시간, 분, 초로 가공해주는 역할을 한다.

nowDate : 현재 일자를 불러오는 변수로, new Date() 함수를 이용해 오늘의 날짜를 가져온다.
targetDate : 목표 날짜의 값이 입력되기 이전 즉, 초기 값을 0으로 설정한다.
remaining : 목표 날짜와 현재 날짜의 차이를 초 단위로 나타내는 변수이다.

변수 선언이 끝나고 나서 세 가지의 조건문을 담아, 목표 날짜와 현재 날짜에서 이상이 있을 때를 나타낼 유효성 검사를 위해 사용하였다.

첫 번째 조건문은 목표 날짜와 현재 날짜가 동일할 때, 타이머를 종료시키고 이에 대한 알림 문구를 나타내 준다.
두 번째 조건문은 date 타입과 맞지 않은 잘못된 값을 입력하였을 때 나타내줄 조건이다.
세 번째 조건문은 date 타입과는 동일하나 현재 날짜 대비 목표 날짜가 지난 일자라면 알려주는 조건 문이다.

각 각의 조건 문에는 이전의 HTML Element가 사라지고 필요한 Element가 나오도록 css 속성도 추가를 하고,
아래서 확인해볼 resetTimer() 함수를 이용해, 해당 조건문이 실행될 때, 카운터 혹은 일자 계산이 되지 않도록 구성하였다.

remainingObj : "일", "시간", "분", "초"에 해당하는 값들을 Map 형태로 저장해두어, key, value 값을 가지도록 하였다.
documentArr : "일", "시간", "분", "초"에 해당하는 요소의 ID와, JS에서 사용할 ID를 일치시키고 VALUE 값을 편하게 사용하기 위해 배열에 해당 ID를 추가시키고 이후에 반복문을 통해 간편하게 아이디와 값을 불러올 수 있도록 처리했다.
timeKeys : 아까 remainingObj를 키와 값 형태로 구성을 해두었는데, 이에 대한 키값을 편하게 가져오기 위해 사용하였다.

format() : 해당 함수 없이 구성을 하면, '초'가 10이하로 떨어지면 일 단위로 떨어지기 때문에 전체 화면에서 보여질 때 어색해보여 10초 이하로 떨어지면 09, 08, 07로 표현될 수 있도록 처리하였다.

var i = 0;
for(var tag of documentArr){
    const remainingTime = format(remainingObj[timeKeys[i]]);
    document.getElementById(tag).textContent = remainingTime;
    i++;
}

마지막에 위 반복문을 통해서, 계산된 "일", "시간", "분", "초"에 대한 값을 순서대로 불러온 뒤, 앞서 만든 format에 가져와 remainingTime 변수에 담아준다.
그리고 담은 값은 var tag of documentArr 즉, 위에서 배열로 만들어준 "days","hours","min","sec" 태그에 순서대로 위에서 계산된 remainingTime의 값을 넣어 "일", "시간", "분", "초"가 바로 확인될 수 있도록 처리한다.


starter() 함수

const starter = function() {
    const targetDateInput = dateFormMaker();
    container.style.display = "flex";
    msgContainer.style.display = "none";
    setClearInterval();
    counterMaker(targetDateInput);
    
    const intervalId = setInterval(()=> {counterMaker(targetDateInput);}, 1000 ); // 반환값이 해당 Interval의 아이디
    intervalArr.push(intervalId);
}

starter(). 함수는 실제로 화면에서 동작할 수 있도록 위에서 만든 카운터 동작을 실행시켜주는 함수이다.
처음에 Interval을 사용하지 않고 구현을 하니 반복된 동작만 할 뿐, 실제로 카운터가 동작하지 않았다.
그래서 setInterval() 함수를 이용해 위에서 만든 counterMaker를 1초 주기로 동작을 시켜주니 실제로 카운터가 동작하는 것 처럼 나타낼 수 있었다.

그리고 이것을 공부하다가 알게된 사실은 setInterval() 함수가 동작할 때마다 하나의 아이디가 생성된다는 것이었다.
이를 이용해 JS 구문이 도는 최상단에서 intervalArr 배열을 만들어, Interval이 실행될 때마다 각 각의 ID를 담아서 저장하고, 타이머 초기화 버튼을 누를 때, 해당 ClearInterval()을 이용해 해당 배열을 비워주면 타이머가 동작하지 않고 초기화되는 기능을 구현할 수 있었다.

const msgContainer = document.querySelector("#d-day-message");
const container = document.querySelector("#d-day-container");
const intervalArr = [];

container.style.display = "none";
msgContainer.innerHTML = "<h3>D-day를 입력해주세요.</h3>";

setClearInterval() 함수

const setClearInterval = function(){
    for(var i = 0; i<intervalArr.length; i++){
        clearInterval(intervalArr[i]);
    }
}

setClearInterval 함수 setInterval함수가 동작할 때, 만들어진 Interval들을 한 번에 삭제시켜주는 역할을 한다.
위에서 만든 intervalArr 배열의 길이 만큼 ClearInterval() 함수를 쉽고 빠르게 초기화를 해줄 수가 있다.


resetTimer() 함수

const resetTimer = function(){
    container.style.display = "none";
    msgContainer.innerHTML = "<h3>D-day를 입력해주세요.</h3>";
    msgContainer.style.display = "flex";
    setClearInterval();
}

resetTimer()는 타이머 초기화버튼을 눌렀을 때 사용하는 동작으로, setClearInterval() 동작과 html 스타일을 어떤 식으로 처리해줄 지 구현한 코드이다.


이렇게 오늘은 위와 같이 new Date함수를 이용해 D-day 카운트 기능을 직접 구현해보았다.
이렇게 공부하면서 이전에는 몰랐던 Interval의 기능과 실행시마다 ID가 생성된다는 것을 알게되었고, 절절하게 
clearInterval을 사용해줌으로써, 쓸데없는 동작을 방지해줄 수 있다는 것을 알 수 있었다.

728x90

'Programming > JavaScript' 카테고리의 다른 글

[JS] To do List 구현  (0) 2024.06.13
[JS] Local Storage  (2) 2024.06.13
[JavaScript] 날짜를 생성하는 New Date  (0) 2024.06.11
[JavsScript] API 활용  (0) 2024.03.07
[JavaScript] 비동기 AJAX  (0) 2024.03.07