[JavaScript] Moment.js를 이용하여 Date 다루기

dojunggeun·4일 전
0

자바스크립트에서 날짜, 시간을 다루는 것은 항상 번거롭다. 네이티브 date 메소드는 지저분하고 API는 일관성이 부족하다. 그래서 Stackoverlow에 date와 관련된 질문을 하면 "Moment.js를 쓰세요"라는 답변을 자주 듣게 된다.

Mometn.js는 무엇인가? : What Is Moment.js?

Moment.js는 자바스크립트에서 dates를 다루기 위한 Swiss Army knife(맥가이버칼)이다. 깔끔하고 간결한 API를 이용해서 날짜와 시간을 분석, 검증, 조작, 표시할 수 있다.

이 글은 Moment.js를 시작하고 실행하는 방법과 몇 가지 일반적인 사용법을 보여준다.

Moment.js 시작하기 : Getting Started with Moment.js

Moment.js는 프로젝트의 홈페이지에서 무료로 다운로드해서 사용할 수 있다. Moment.js는 Node 애플리케이션 내에서처럼 브라우저에서도 사용할 수 있다. Node와 함께 사용하려면, 다음 명령어로 모듈을 설치하면 된다.

npm install moment

설치 후 require()하면 아래와 같이 당신의 애플리케이션에서 간편하게 사용할 수 있다.

const moment = require('moment');
const today = moment();
console.log(today.format());

// 2020-01-09T15:45:51+01:00

Moment.js를 브라우저에서 실행하려면 아래와 같이 <script>태그 내에서 사용해야한다. Moment.js는 모든 date와 time을 분석하고 조작하는 기능을 포함하는 전역(global) moment 객체를 만든다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Moment.js</title>
  </head>
  <body>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
    <script>
      // You have a 'moment' global here
      const today = moment();
      console.log(today.format());
    </script>
  </body>
</html>

Date 형식 지정 : Date Formatting

이전에는 date 문자열을 Date 객체로 변환하기 위해 개별 데이터를 추출해서 문자열을 연결해야 했다. Moment.js는 date를 어떤 형식으로든 간단하게 변환할 수 있는 기능을 제공한다. Moment를 이용한 Date 형식 변경은 아래의 예시처럼 심플하다.

moment().format('YYYY-MM-DD');

moment()를 호출하면 우리는 현재 날짜와 시각을 얻을 수 있고, format()은 이를 지정된 형식으로 변환해준다. 이 예시는 date를 하이픈(-)으로 연결되는 4자리 연도, 2자리 달, 2자리 날짜 형식으로 지정한 것이다.

팁: 공식 문서에 기재된 다양한 date 형식을 적용해보세요.

Data 검증 : Date Validation

Moment.js가 크게 단순화한 또 다른 작업은 date 검증이다. 유효성 검증을 수행하려면 원하는 date 형식과 함께 날짜 문자열을 moment 객체에 전달하고 isValid() 메서드를 호출하면 된다. date가 유효하면 true를, 유효하지 않으면 false를 반환한다.

console.log(moment("2020-01-01", "YYYY-MM-DD").isValid()); // true
console.log(moment("not-a-date", "YYYY-MM-DD").isValid()); // false

그러나 Moment는 date 형식의 일부분만 작업할 수 있는 가능성을 제공하기 때문에, 예상과 다른 결과가 반환될 수 있다는 점에 유의하라.

console.log(
  moment("2019 was a great year because I got married", "YYYY-MM-DD").isValid()
);
// 2019가 YYYY의 형식과 일치하기 때문에 true를 반환한다

이런 상황을 피하기 위해 3번째 인자로 true를 입력하여 Moment를 엄격 분석 모드(strick parsing mode)로 설정할 수 있다.

console.log(
  moment("2019 was a great year because I got married", "YYYY-MM-DD", true).isValid()
);
// false

이 기능을 보여주는 예시가 있다.

moment()가 반환하는 객체에는 다양한 flag들이 있다.

  • overflow – overflow가 발생했을 때 (13월이나 32일 등을 입력했을 때)
  • invalidMonth – month가 유효하지 않을 때 (Jannnuaarry 등)
  • empty – 입력된 date가 분석 가능한 어떤 것도 포함하지 않을 때
  • nullInput – 입력된 date가 null일 때

공식 홈페이지에서 이것들과 다른 가능한 결과들에 대해 읽어볼 수 있다.

Date 조작하기 : Manipulating Dates

moment 객체를 조작하는 다양한 옵션들이 있다. 예를 들면, days, months, years 등을 더하거나 뺄 수 있다. add()subtract() 메소드를 이용하면 된다. 아래 예시는 어떻게 7일, 7달, 7년을 더하는지 보여준다.

moment().add(7, 'days');    // 현재 날짜에 7일을 더한다
moment().add(7, 'months');  // 현재 날짜에 7개월을 더한다
moment().add(7, 'years');   // 현재 날짜에 7년을 더한다

비슷하게, subtract() 메소드는 아래와 같다.

moment().subtract(7, 'days');   // 현재 날짜에서 7일을 뺀다
moment().subtract(7, 'months'); // 현재 날짜에서 7개월을 뺀다
moment().subtract(7, 'years');  // 현재 날짜에서 7년을 뺀다

각 예시들은 moment 객체를 반환할 것임을 기억하라. 사람이 읽을 수 있는 방식의 날짜를 원한다면, 아래와 같이 형식을 지정하라.

const today = moment();
const nextWeek = today.add(7, 'days');
console.log(nextWeek.format('dddd Do MMMM, YYYY'));
// Thursday 16th January, 2020

Time From Now

다른 일반적인 작업은 두 날짜 사이의 시간을 다루는 것이다. 현재 시점으로부터의 시간 차이를 계산하기 위해, Moment.js는 fromNow() 메소드를 사용한다. 2020년 1월 1일로부터 얼마나 많은 시간이 흘렀는지 확인하는 방법은 다음과 같다:

moment('2020.01.01', 'YYYY.MM.DD').fromNow();
// 9 days ago

만약 true를 인자로 입력하면, 접미사가 없는 값을 얻는다.

moment('2020.01.01', 'YYYY.MM.DD').fromNow(true);
// 9 days

Time From Another Date

fromNow() 멧드는 현재 시점과의 비교를 위해 사용된다. 이는 두 임의의 date를 비교하는 from()의 특별한 케이스다. form()의 사용 방식은 아래에 나와있다.

const dateA = moment('01-01-1900', 'DD-MM-YYYY');
const dateB = moment('01-01-2000', 'DD-MM-YYYY');

console.log(dateA.from(dateB));

이 메소드를 아래의 데모를 통해 직접 사용해볼 수 있다.

두 날짜의 차이 계산 : Calculating the Difference Between Dates

Moment.js는 두 날짜의 차이를 계산하는 방법을 제공한다. 차이는 기본적으로 밀리초 단위로 계산되지만 일, 월, 년 등의 단위로도 반환할 수 있다. 차이를 계산하려면 diff() 메서드를 호출하면 된다. 이 방법은 날짜를 첫 번째 인자로 받는다. 시간 단위는 선택적인 두 번째 인자를 사용하여 지정할 수 있다. 두 번째 인자가 입력되지 않으면 기본값인 밀리초가 사용된다. 다음의 예와 데모는 diff()가 어떻게 사용되는지 보여준다.

const dateB = moment('2014-11-11');
const dateC = moment('2014-10-11');

console.log('Difference is ', dateB.diff(dateC), 'milliseconds');
console.log('Difference is ', dateB.diff(dateC, 'days'), 'days');
console.log('Difference is ', dateB.diff(dateC, 'months'), 'months');

Date Queries

Moment.js는 날짜를 비교하는 다양한 메소드들을 제공한다. 이 메소드들은 이름에서 의미를 알 수 있는 isBefore(), isAfter(), isSame()를 포함한다. 이들은 각각 Boolean을 결과로 반환한다. isAfter()의 사용법은 아래를 보라.

console.log(moment('2020-01-01').isAfter('2019-01-01')); // true
console.log(moment('2020-01-01').isAfter('2020-01-08')); // false

윤년을 확인하는 isLeapYear()메소드도 있다.

console.log(moment([2020]).isLeapYear()); // true
console.log(moment([2019]).isLeapYear()); // false

언어 지원 : International Language Support

Moment.js는 훌륭한 i18n 지원을 제공한다. global 언어를 할당하거나 특정한 moment 객체에 언어를 할당할 수 있다. 기본적으로 영어를 지원한다. 다른 언어를 지원하고 싶다면, 특정 언어를 moment.locale에 할당하라. Moment.js 공식 문서에서 인용한 다음의 예시는 프랑스어에 대한 지원을 어떻게 추가할 수 있는지 보여준다.

const moment = require('moment');

moment.locale('fr', {
  months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
  weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
  relativeTime : {
      future : 'dans %s',
      past : 'il y a %s',
      s : 'quelques secondes',
      m : 'une minute',
      mm : '%d minutes',
      h : 'une heure',
      hh : '%d heures',
      d : 'un jour',
      dd : '%d jours',
      M : 'un mois',
      MM : '%d mois',
      y : 'un an',
      yy : '%d ans'
  }
});

moment.locale('fr');

console.log(moment(1316116057189).fromNow());
// il y a une heure

console.log(moment().format('dddd Do MMMM, YYYY'));
// jeudi 9e janvier, 2020

Moment와 잘 맞지 않을 수 있는 이유 : Why Moment Might Not Be a Good Fit

비록 Moment.js가 훌륭한 라이브러리이지만, 다소 무겁기도 하다. 예로, 웹팩과 함께 사용하면 순수한 require('moment')만으로 모든 locales를 사용할 수 있다. 이렇게 하면 번들의 크기가 꽤 커지기 때문에 플러그인을 사용해서 다듬어야 한다.

Moment.js는 많은 훌륭한 기능이 있지만, Lodash같은 라이브러리와는 달리, 필요한 기능만 골라낼 수 없다. 항상 라이브러리 전체를 로드해야 한다.

다른 일반적인 불만은 moment 객체가 가변적이라는 것이다. 이는 개발자들에게 혼란을 야기할 수 있다. 생각해보라:

const moment = require('moment');
const today = moment();
const nextWeek = today.add(7, 'days');
console.log(today.fromNow());

콘솔에 무엇이 찍힐 것이라 예상하는가? 불행히도, 답은 "in 7 days"이다. ("a few seconds ago"가 아니다) 이는 today.add(7, 'days')가 today 객체를 7일 후로 수정했기 때문이다.

이는 moment 객체를 계산에 다루기 전에 복사하는 방식으로 피할 수 있지만, 당신이 이 사실을 기억해내기 전까지 많은 시간을 디버깅에 낭비했을 수 있다.

const moment = require('moment');
const today = moment();
const nextWeek = today.clone().add(7, 'days');
console.log(today.fromNow());
// a few seconds ago

가벼운 대안 : A Light-weight Alternative

좀 더 가벼운 대안을 찾고싶다면 date-fns를 고려해라. Date-fns는 불변적이기에, 기존의 객체를 수정하는 대신 항상 새로운 객체를 반환한다. API도 간단하고, 웹팩과 잘 어울리고, function-per-file 시스템을 통해 당신이 필요한 것만 선택할 수 있다.

자세한 내용은 다음을 참고하라: Introduction to date-fns – a Lightweight JavaScript Date Library

결론 : Conclusion

Moment.js는 시간과 날짜를 다루고 검증하는데 정말 좋은 라이브러리다. 이 글에서 우리는 브라우저와 Node에서 시간과 날짜를 분석, 검증, 조작하는 여러 방법에 집중했다. Moment.js에 여러 유용한 플러그인들도 사용할 수 있다. ISO Calendar, Jalaali Calendar를 비롯하여 공식 플러그인 페이지에서 다양한 플러그인 찾을 수 있다. Moment.js에 대해 더 알고싶다면 라이브러리의 공식 문서를 읽어보라.

0개의 댓글