FrontEnd

[JS📜] 자바스크립트의 시간은 브라우저마다 다르다

머털박사 2022. 8. 14. 16:47

 

이 포스팅은 자바스크립트 내장 객체 Date를 다루는 방법과 문제점, 문제점을 해결하기 위한 다른 라이브러리에 대해서 다룹니다.

오늘 날짜를 생성하는 방법

자바스트립트에서 날짜를 생성하는 방법은 두가지다. 첫 번째는 Date() 함수만 호출하는 방법, 두 번째는 new Date() 로 호출하는 방법이다.

const 함수로호출 = Date();
console.log(함수로호출) // Fri Jun 24 2022 11:41:00 GMT+0900 (대한민국 표준시)
console.log(typeof 함수로호출);// string

const 생성자로호출 = new Date();
console.log(생성자로호출) // Fri Jun 24 2022 11:41:00 GMT+0900 (대한민국 표준시)
console.log(typeof 생성자로호출); //object

Date() 로 생성한 날짜는 문자열을 반환하고, new Date()로 생성한 경우 새로운 Date 객체를 반환한다.

console.log(함수로호출.toLowerCase()); // fri jun 24 2022 14:25:11 gmt+0900
console.log(생성자로호출.getTime()); // 167417280000

Date()함수로 호출한 값은 String이라 replace, length 같은 String 메서드만 사용할 수 있다. new Date() 생성자로 호출한 경우 새로운 getDate(), getDay() 와 같은 메서드를 사용할 수있다.

자바스크립트 Date() 객체의 문제

console.log(new Date(Date.parse("Jul 8, 2022")))
//Fri Jul 08 2022 00:00:00 GMT+0900 (대한민국 표준시)

console.log(new Date(Date.parse("2022-07-08")))
//Fri Jul 08 2022 09:00:00 GMT+0900

참고: Date.parse()를 사용한 날짜 분석은 브라우저 간 차이 및 일관적이지 못한 동작을 가지고 있으므로 사용하지 않는 것이 좋습니다. -MDN-

위처럼 같은 값을 넣어도 다른 결과가 나온다. 그렇다면 Date 관련 메소드 중에서 parse() 만 안 쓰면 되는 거 아닌가? 싶었지만 다른 문제가 있었다. **new Date() 생성자 자체가 내부에 .parse() 메서드를 사용하고 있다.**

console.log(new Date())

// Chrome, Fri Jun 24 2022 17:20:23 GMT+0900 (한국 표준시)
// Edge, Fri Jun 24 2022 17:21:07 GMT+0900 (한국 표준시)
// Firefox, Fri Jun 24 2022 17:21:07 GMT+0900 (대한민국 표준시)
// SafariSat, Fri Jun 24 2022 17:21:07 GMT+0900 (KST)

그래서 new Date()로 날짜를 만든 경우 서로 다른 기준으로 시간이 나온다. 이러한 가변적인 특성때문에 시간을 다룰 때는 라이브러리를 사용하길 권장하고 있다.

자바스크립트 날짜 다루는 맥가이버 라이브러리 moment.js

네이티브 데이터 메소드는 위와 같이 일관성이 부족하여 보통은 라이브러리를 사용한다. 깔끔하고 간결한 API를 통해 날짜와 시간을 분석, 검증, 조작, 표시할 수 있다.

new Date(2007, 0, 27) - new Date(2007, 0, 29);
// => -172800000
Math.ceil(
  (new Date(2007, 0, 27) - new Date(2007, 0, 29)) / 1000 / 60 / 60 / 24
); 
// => -2

예를 들면 특정 날짜 사이의 일수 구하려면 네이티브로는 위와 같이 1000(1초) * 60(1초가 60번 = 1분) * 60(1분이 60번 = 1시간) * 24(1시간이 24번 = 하루) 이런 식으로 복잡한 계산을 해야한다.

moment([2007, 0, 27]).diff(moment([2007, 0, 29]));
// => -172800000
moment([2007, 0, 27]).diff(moment([2007, 0, 29]), 'days');
// => -2

하지만 moment.js는 위와 같이 간결하게 사용할 수 있다!

moment.js : 업데이트 안 합니다. 저희 라이브라리 더 이상 사용하지 마세요.

네…? 벌써 썼는데요?

네…? 벌써 썼는데요?

2020년 9월에 moment.js 사망선고가 내려졌다. 2011년도에 만들어진 오래된 라이브러리라 현대 웹에서는 꽤 문제가 많다. moment.js를 사용하지 말아야 할 이유라는 레포지토리에 별이 만 개나 찍힐정도다.

이슈가 많지만 해결하면 아예 코드를 다 뜯어고쳐야했다고 한다. 이미 moment.js 사용하는 곳이 많기 때문에 위험한 도전을 하기보단 안정성을 선택한 것이다.

대체재를 찾아보자(date-fns, dayjs, luxon)

 

moment.js처럼 자바스크립트에서 시간을 다루는 라이브러리는 대표적으로 date-fns, dayjs, luxon이 있다. 기본적으로 나는 항상 라이브러리를 사용할 때 일단 npm 다운로드 수를 확인하는 편이다. 웬만해서는 많이 사용하는 라이브러리가 자료가 많아서 개발할 때 편하다.

이름 주간 다운로드 수(2022-06-24) 사이즈 출시연도 깃주소
date-fns 13,667,683 6.47 MB 2015년
dayjs 10,551,237 644 kB 2018년
Luxon 3,624,780 3.05MB 2017년
momentjs 4.23 MB 4.23 MB 2011년

다운로드 수

  • momentjs> date-fns> dayjs> luxon

사이즈

  • momentjs> date-fns> luxon> dayjs

최근에 출시한 순

  • dayjs> date-fns> luxon> momentjs

문법

날짜 사이의 시간을 얻는 방법이다.

// Moment.js
moment([2007, 0, 27]).diff(moment([2007, 0, 29]));
// => -172800000
moment([2007, 0, 27]).diff(moment([2007, 0, 29]), 'days');
// => -2

// Native
new Date(2007, 0, 27) - new Date(2007, 0, 29);
// => -172800000
Math.ceil(
  (new Date(2007, 0, 27) - new Date(2007, 0, 29)) / 1000 / 60 / 60 / 24
);
// => -2

// date-fns
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds';
differenceInMilliseconds(new Date(2007, 0, 27), new Date(2007, 0, 29));
// => -172800000
import differenceInDays from 'date-fns/differenceInDays';
differenceInDays(new Date(2007, 0, 27), new Date(2007, 0, 29));
// => -2

// dayjs
dayjs('2007-01-27').diff(dayjs('2007-01-29'), 'milliseconds');
// => -172800000
dayjs('2007-01-27').diff(dayjs('2007-01-29'), 'days');
// => -2

// luxon
DateTime.local(2007, 1, 27).diff(DateTime.local(2007, 1, 29)).milliseconds;
// => -172800000
DateTime.local(2007, 1, 27).diff(DateTime.local(2007, 1, 29), 'days').days;
// => -2

// Temporal
Temporal.PlainDate.from('2007-01-27').since('2007-01-29').total({unit: 'millisecond'});
// => -172800000
Temporal.PlainDate.from('2007-01-27').since('2007-01-29').total({unit: 'day'});
// => -2

개인적으로는 dayjs가 제일 마음에 들었다. 용량도 작고, 추가적인 모듈만 다운받으면 대부분의 기능도 쓸 수 있고, 문법도 momentjs와 비슷해서 적응하기 편할 것 같다.

 

 


참고자료

Date - JavaScript | MDN

왜 moment 는 deprecated 되었을까

Goodbye Moment (feat. Dayjs)

[리빙 포인트] 브라우저에서 Date 객체를 사용하고 싶을 땐

GitHub - you-dont-need/You-Dont-Need-Momentjs: List of functions which you can use to replace moment.js + ESLint Plugin