Vue 남은 시간 - Vue nam-eun sigan

아내의 수유 시간 체크와 업무 중 자리 비운 시간을 체크하기 위해 토이 프로젝트로 타이머를 만들어 보았습니다.
간단하고 쉽게 만들자 컨셉에 맞춰 레트로 스타일로 만들었습니다. 이름하여 8비트 타이머!

Vue 남은 시간 - Vue nam-eun sigan

https://timer.moonspam.com/

일단 만들어 보자

신식이 최고야!라고 외치는 나의 성격 탓에 틈틈이 시도해보고 있는 vue.js를 이용해 타이머를 만들어보기로 했습니다.

Vue CLI

Vue.js에서 공식 지원하고 있다는 Vue CLI를 통해 쉽게 프로젝트 생성을 할 수 있었습니다.
3.x 버전부터 GUI 인터페이스로 프로젝트를 관리할 수 있게 바뀌었더군요.

설치와 실행은 간단합니다.

설치

GUI 실행

Vue 남은 시간 - Vue nam-eun sigan

Vue 프로젝트 매니저를 통해 기본 템플릿을 설정하고 서버를 구동하며 시작이 반이라고 반이나 했다!라는 생각도 잠시… setInterval로 시간을 1초씩 차감하면 될 거라고 생각했지만 어떻게 구성하여 풀어나가야 할지 막막했습니다.

이미 제작된 여러 타이머 소스들을 보던 와중 쉽고 이해하기 편한 예시를 찾았습니다.
매번 이런 소스들을 볼 때마다 이렇게 쉽게 풀 수 있는 걸 어렵게 고민하고 있었을까? 반성하게 됩니다.

아래는 제가 만든 타이머의 큰 틀을 잡아준 코드입니다.

See the Pen Vue: Timer ⇢ WIP by Joshua Ward (@joshuaward) on CodePen.

예쁘게 꾸며보자

조금 코딩하고 바로 꾸미기에 돌입! 주로 모바일로 볼 거라 페이지 레이아웃을 display: flex를 이용해 제작했습니다. flex를 이용해 한땀 한땀 width 값을 넣지 않아도 알아서 조절되고 여러 줄을 써서 가운데 정렬했던 부분을 한 줄로 끝내는 등 편리한 부분이 많았습니다.
언젠간 사용해봐야지 했던 NES.css도 적용하여 레트로 스타일 레이아웃 완성!

먼가 부족해

Vue.js 공식 문서를 보면서 꾸역꾸역 완성할 때 즈음 모바일에서 테스트해보니 추가하고 싶은 부분들 발생…
작업 중에 추가한 기능들을 나열해 보았습니다.

  • 전체 화면 구현 스크립트 추가 🔗
  • 모바일에서 화면 안 꺼지게 해주는 기능 추가 🔗
  • 남은 시간 5분, 정각에 진동 울리기 추가 (iOS에서는 안됨)
  • dialog 태그를 사용하기 위한 dialog-polyfill 🔗
  • 파비콘을 쉽게 넣고 싶어서 찾은 favicon.io 🔗

후기

프로젝트를 진행하면서 Vue.js가 어떤 형태로 돌아가는지 수박 겉핥기 식으로 훑었지만 토이 프로젝트에 맞게 재밌게 코딩한 작업이었습니다.

Date는 자바스크립트에 내장되어있는 객체로 1970년 1월 1일 00:00 UTC(국제 표준시)으로부터 지난 시간을 밀리세컨드 단위로 나타내는 유닉스 타임스탬프를 사용합니다.

밀리초/밀리세컨드(millisecond, ms)?
1000분의 1초를 나타내는 단위로 1000밀리세컨드는 1초와 같다.

Date사용해보기

new연산자를 사용해 Date객체를 생성. 아무런 인자값을 넣지 않으면 기본으로 생성한 시점의 시간으로 생성됨.

const CURRENT_DATE = new Date();
console.log(CURRENT_DATE);
Vue 남은 시간 - Vue nam-eun sigan

특정 날짜로 Date객체를 생성하려면 인자값으로 특정 날짜를 입력.

const BIRTH_DAY = new Date("1995-12-28");

+) 두 날짜간의 차이(일 수) 구하기

function getDiff() {
  const currDay = new Date();
  const birthDay = new Date(`${currDay.getFullYear()}-12-28`);

  const diffDays = Math.floor((birthDay.getTime() - currDay.getTime()) / (1000 * 60 * 60 * 24));
  console.log(`생일까지 ${diffDays < 10 ? `0${diffDays}` : diffDays}일 남았습니다.`);
}
Vue 남은 시간 - Vue nam-eun sigan

+) 두 날짜간의 차이(일, 시간, 분, 초) 구하기

function getTime() {
  const xmasDay = new Date("2020-12-25");
  const currDay = new Date();

  let diff = xmasDay - currDay;
  const diffDays = Math.floor((xmasDay.getTime() - currDay.getTime()) / (1000 * 60 * 60 * 24));
  diff -= diffDays * (1000 * 60 * 60 * 24);
  const diffHours = Math.floor(diff / (1000 * 60 * 60));
  diff -= diffHours * (1000 * 60 * 60);
  const diffMin = Math.floor(diff / (1000 * 60));
  diff -= diffMin * (1000 * 60);
  const diffSec = Math.floor(diff / 1000);
  
  console.log(`${diffDays < 10 ? `0${diffDays}` : diffDays}일 ${diffHours < 10 ? `0${diffHours}` : diffHours}시간 ${diffMin < 10 ? `0${diffMin}` : diffMin}분 ${diffSec < 10 ? `0${diffSec}` : diffSec}초`);

}

퍼블리셔의 다이어리

function remaindTime() {
    var now = new Date(); //현재시간을 구한다. 
    var end = new Date(now.getFullYear(),now.getMonth(),now.getDate(),21,00,00);

//오늘날짜의 저녁 9시 - 종료시간기준
    var open = new Date(now.getFullYear(),now.getMonth(),now.getDate(),09,00,00);

//오늘날짜의 오전9시 - 오픈시간기준
  
    var nt = now.getTime(); // 현재의 시간만 가져온다
    var ot = open.getTime(); // 오픈시간만 가져온다
    var et = end.getTime(); // 종료시간만 가져온다.
  
   if(nt<ot){ //현재시간이 오픈시간보다 이르면 오픈시간까지의 남은 시간을 구한다. 
     $(".time").fadeIn();
     $("p.time-title").html("금일 오픈까지 남은 시간");

     sec =parseInt(ot - nt) / 1000;
     day  = parseInt(sec/60/60/24);
     sec = (sec - (day * 60 * 60 * 24));
     hour = parseInt(sec/60/60);
     sec = (sec - (hour*60*60));
     min = parseInt(sec/60);
     sec = parseInt(sec-(min*60));
     if(hour<10){hour="0"+hour;}
     if(min<10){min="0"+min;}
     if(sec<10){sec="0"+sec;}
      $(".hours").html(hour);
      $(".minutes").html(min);
      $(".seconds").html(sec);
   } else if(nt>et){ //현재시간이 종료시간보다 크면
    $("p.time-title").html("금일 마감");
    $(".time").fadeOut();
   }else { //현재시간이 오픈시간보다 늦고 마감시간보다 이르면 마감시간까지 남은 시간을 구한다. 
       $(".time").fadeIn();
     $("p.time-title").html("금일 마감까지 남은 시간");
     sec =parseInt(et - nt) / 1000;
     day  = parseInt(sec/60/60/24);
     sec = (sec - (day * 60 * 60 * 24));
     hour = parseInt(sec/60/60);
     sec = (sec - (hour*60*60));
     min = parseInt(sec/60);
     sec = parseInt(sec-(min*60));
     if(hour<10){hour="0"+hour;}
     if(min<10){min="0"+min;}
     if(sec<10){sec="0"+sec;}
      $(".hours").html(hour);
      $(".minutes").html(min);
      $(".seconds").html(sec);
   }
 }
 setInterval(remaindTime,1000); //1초마다 검사를 해주면 실시간으로 시간을 알 수 있다.