JavaScript의 Date는 JavaScript 날짜의 기반은 1970년 1월 1일 UTC 자정과의 시간 차이를 밀리초 단위로 나타낸다.
let today = new Date();
let birthday = new Date('December 17, 1995 03:24:00');
let birthday = new Date('1995-12-17T03:24:00');
let birthday = new Date(1995, 11, 17); // 월은 0부터 시작
let birthday = new Date(1995, 11, 17, 3, 24, 0);
하지만 많은 javascript 개발자들은 Date API 대신 다른 라이브러리 등을 채택하여 사용한다. 어떤 문제점이 있기에 기본 스펙 대신 라이브러리를 사용하는 것이 자연스러워졌을까?
Date 객체를 이용하면 시간까지 포함된 datetime이 생성되어, 날짜만 사용하고 싶어도 사용할 수 없도록 구현되어 있다.
let date = new Date(2011, 1, 22);
// Tue Feb 22 2011 00:00:00 GMT+0000 (Greenwich Mean Time)
new Date
호출 시에 실행되는 Date.parse
함수가 브라우저나 버전마다 구현이 다르다. 어떤 브라우저는 UTC기준, 또 어떤 브라우저는 해당 브라우저가 속한 Timezone 기준으로 해석하여 문제가 발생할 수 있다.
DateString으로 date 객체 생성시 UTC 기준으로 date가 생성되어 오차 발생 가능성이 있다. 아래의 경우 단순히 Date.parse
함수를 호출하여 timestamp를 생성한 것으로 보인다. 그러나 timezone에 따라 문제가 발생할 수 있다.
let myDate = Date.parse('01 Jan 1999');
마지막 경우에 JavaScript는 Unix timestamp에서 5시간을 뺀다. 앞서 언급된 JavaScript는 date 단독으로는 사용할 수 없다는 사실에 따라 1st Jan 1999가 아니라 31st Dec 1998라는 당황스러운 결과를 얻게 된다.
만약 2011년 2월 22일에 대한 date를 생성하고 싶다면 아래와 같이 작성하면 될 것이라 예상된다.
let date = new Date(2011, 2, 22);
사실은 아니다! JavaScript의 월은 일, 연과 다르게 0부터 시작되어 아래와 같이 두번째 인자에 “1”을 작성해야 한다. 어렵진 않아도 헷갈린다.
let date = new Date(2011, 1, 22);
이렇게 다양한 문제를 안고 있는 Date 객체를 그대로 사용하는 것이 가장 좋은 방법이라고 하기엔 무리가 있어보인다. 그렇다면 어떤 대안들이 있을까?
JavaScript 날짜 관련 라이브러리 중 가장 많이 사용된다. 현재는 더 이상의 업데이트가 없을 것이라 공지 되었으나, 여전히 많이 채택되고 있다.
날짜 관련 코드 중에 굉장히 자주 사용되는 “몇분전”, “몇년전”을 나타내는 코드를 Vanilla JS로 작성한다면 다음과 같을 것이다.
function timeForToday(value: string) {
const today = new Date();
const timeValue = new Date(value);
const betweenTime = Math.floor((today.getTime() - timeValue.getTime()) / 1000 / 60);
if (betweenTime < 1) return '방금전';
if (betweenTime < 60) {
return `${betweenTime}분전`;
}
const betweenTimeHour = Math.floor(betweenTime / 60);
if (betweenTimeHour < 24) {
return `${betweenTimeHour}시간전`;
}
const betweenTimeDay = Math.floor(betweenTime / 60 / 24);
if (betweenTimeDay < 365) {
return `${betweenTimeDay}일전`;
}
return `${Math.floor(betweenTimeDay / 365)}년전`;
}
그러나 momentjs를 이용한다면 내장 함수로 간단하게 작성할 수 있다.
import moment from 'moment';
import 'moment/dist/locale/ko';
export function timeForToday(createdAt: string) {
return moment(createdAt).locale('ko').fromNow();
}
기존의 JavaScript 객체가 가진 문제점들을 모두 해결하면서, 편리한 기능도 장착하고 있으니 고려해볼만한 선택지이다.
JavaScript 진영에서도 현대적인 date API를 준비하고 있다. 현재 stage 3 proposal 단계로 실험적으로 운영되고 있으나 곧 표준에 포함될 것이라 예상된다.
아래와 같이 사용 가능하다.
// 현재 시간대
Temporal.Now.timeZone(); // Temporal.TimeZone 객체를 반환
Temporal.Now.timeZone().id; // "Asia/Seoul"
// 현재 시간에 대한 Unix timestamp
Temporal.Now.instant().epochSeconds;
Temporal.Now.instant().epochMilliseconds;
// 시간 단독
new Temporal.PlainTime(11, 22, 33);
Temporal.PlainTime.from('11:22:33');
// 날짜 단독
new Temporal.PlainDate(1996, 2, 21);
Temporal.PlainDate.from('1996-2-21');
// 시간, 날짜
new Temporal.PlainDateTime(1996, 2, 21, 15, 30, 50);
Temporal.PlainDateTime.from('1996-02-21T15:30:50');
JavaScript의 Date API가 가진 문제점들을 대부분 해결하면서도 외부 라이브러리를 가져와 번들 사이즈를 늘릴 이유가 없으니 미리 공부하거나 polyfill을 이용하여 개발하며 표준 스펙에 들어가기를 기다려보는 것도 좋은 선택이 될 것 같다.
Moment.js가 업데이트를 하지 않으면서 공식 문서에서 아래를 포함한 몇개의 대안을 제시해주었다. 해당 문서 내용에서 대안책을 찾아보는 것도 방법이 될 수 있다.
굿 ~ 👍