패키지 매니저 pnpm, 새로운 의존성 관리 방식(vs npm/yarn)

기존의 호이스팅 방식과 pnpm의 의존성 트리 유지 방식

pnpm은 Performant NPM, 즉 높은 성능을 내는 npm이라는 의미이다.

npm은 공식적으로 ‘줄여쓴 약자가 아니다(npm is not an acronym)’라고 하지만 누구에게나 Node Package Manager라고 하면 쉽게 설명이 된다…

회사 프로젝트에서도 npm yarn yarn berry를 거쳐 현재는 pnpm을 기본으로 사용하고 있으며, 특성상 낮은 노드 버전 유지가 필요한 곳만 npm을 사용하고 있다.

그렇다면 다른 패키지 매니저와 비교해 pnpm의 특징을 먼저 살펴보자.

특징pnpmnpm / yarn
속도빠름(병렬 처리)다소 느림
효율성좋음(글로벌 캐싱, 링크 사용)낮음(중복 저장 가능성)
호환성npm 호환Node.js 기본
의존성 관리엄격함(충돌 방지 장점)느슨함
모노레포 지원워크스페이스 지원yarn 일부 지원
pnpm과 npm/yarn의 차이

pnpm의 의존성 관리 방식은 기존의 호이스팅(hoisting) 방식을 사용하는 패키지 매니저와 차별화된다. 호이스팅 방식과 pnpm 고유의 의존성 트리 유지 방식을 비교해보자.

호이스팅 방식

전통적인 패키지 매니저(npm, yarn)에서 사용되는 방식으로, 의존성을 프로젝트 루트의 node_modules 디렉토리로 끌어올리는 것을 의미한다.
모든 의존성을 루트 디렉토리에 설치하여, 하위 패키지에서 해당 의존성을 마치 루트에 설치된 것처럼 접근이 가능하도록 한다.

호이스팅 방식의 장점

1. 간단한 접근 : 모든 패키지가 같은 디렉토리에 설치되므로, 의존성을 찾는 데 간단한 구조를 갖는다.

2. 중복 제거 : 중복된 의존성을 상위로 끌어올려 디스크 사용량이 줄어든다.

호이스팅 방식의 단점

1. 의존성 충돌 : 서로 다른 패키지가 동일한 이름의 의존성을 서로 다른 버전으로 요구할 때, 하나의 버전만 설치되므로 충돌 발생 가능성 존재한다.

2. 의존성 숨김 문제 : 하위 패키지가 암묵적으로 루트에 있는 의존성에 접근하게 되어, 의존성을 명시하지 않고 사용할 위험이 있다.

따라서 패키지가 다른 프로젝트에서 독립적으로 작동하지 않을 가능성이 높아진다.

pnpm 고유의 의존성 트리 유지 방식

pnpm은 의존성을 독립적으로 관리하며, 각 패키지의 의존성 트리를 유지한다. 또한 “flat” 구조 대신 하드 링크와 심볼릭 링크를 사용하여, 의존성이 설치된 위치를 참조만 한다.

작동 방식

.pnpm 디렉토리

모든 의존성은 루트의 node_modules 디렉토리 내부 .pnpm 디렉토리에 설치된다. 중복된 의존성은 단일 디렉토리에 저장하고, 필요한 위치에서 해당 파일에 심볼릭 링크를 생성한다.

독립적 의존성 트리

각 패키지는 자신만의 node_modules를 가지고, 필요한 의존성을 .pnpm에서 참조한다.

예를 들면 다음과 같은 구조다.

project/
├── node_modules/
│   ├── package-a/
│   │   └── node_modules/
│   │       └── dependency-a@1.0.0 -> .pnpm/dependency-a@1.0.0
│   ├── package-b/
│   │   └── node_modules/
│   │       └── dependency-a@2.0.0 -> .pnpm/dependency-a@2.0.0

따라서 package-a와 package-b는 서로 다른 버전의 dependency-a를 독립적으로 사용할 수 있다.

pnpm 방식의 장점

1. 의존성 충돌 방지 : 각 패키지가 독립적으로 의존성을 관리하므로, 서로 다른 버전의 의존성을 문제없이 사용할 수 있다.

2. 빠른 설치 : 동일한 의존성을 중복 다운로드하지 않고, 심볼릭 링크를 통해 참조하므로 속도가 빠르다.

3. 디스크 공간 절약 : .pnpm 디렉토리에 모든 의존성을 공유 저장하므로 중복 설치를 방지한다.

4. 명시적 의존성 사용 : 패키지는 반드시 자신이 명시적으로 선언한 의존성만 접근이 가능하며, 루트에 설치된 의존성에 암묵적으로 의존하지 않는다.

pnpm 방식의 단점

1. 복잡한 디렉토리 구조 : 심볼릭 링크를 사용하여 디렉토리 구조가 일반적인 방식보다 복잡해 보일 수 있다.

2. 호환성 문제 : 일부 오래된 라이브러리나 스크립트가 node_modules 트리 구조를 가정한 방식으로 동작할 경우 문제가 생길 수 있다.


pnpm의 의존성 관리 방식은 의존성 충돌 방지, 디스크 공간 절약, 명시적 의존성 관리에 강점을 가지고 있다. 특히 대규모 프로젝트에서 각 패키지의 독립적 의존성을 관리에 매우 유용하다.

참고
https://docs.npmjs.com
https://pnpm.io

렌더링 엔진과 특징 분석하기(webkit, blink, gecko)

독립 발전하는 웹 브라우저 렌더링 엔진

웹 브라우저의 대표적인 렌더링 엔진은 Webkit, Blink, Gecko 세 가지가 있다.

각각의 발전사와 점유율, 특징을 살펴보자.

1. 엔진의 점유율

각 엔진의 점유율은 해당 엔진을 사용하는 브라우저의 점유율 추정치로 살펴보면 다음과 같다.

엔진BlinkWebkitGecko
점유율75%20%3%
브라우저Google Chrome(65%)
Microsoft Edge(5%)
Opera(2.5%)
Samsung Internet(2.5%)
Brabe
Vivaldi
Safari(19%)
iOS용 모든 브라우저
Mozilla Firefox
Statcounter Global Stats – Browser Market Share 참고

‘iOS용 모든 브라우저’는 애플 OS에서 사용되는 크롬, 엣지 등은 Webkit, 이외의 윈도우, 안드로이드 등의 OS에서 사용되는 크롬, 엣지는 Blink를 사용한다는 의미가 된다.

따라서 애플 기기의 브라우저는 모두 Webkit을 사용하며, 이는 전체에서 대략 20%가 된다.

이 같은 특성을 봤을 때 맥 OS에서 개발하고 크롬의 호환성 OK 여부를 결정할 것이 아니라 실제 OS를 변경하여 브라우저 테스트의 필요성이 제기된다.

2. 발전사

Webkit

Webkit은 애플에서 개발한 오픈소스 렌더링 엔진으로 KHTML(1998년부터 사용된 HTML 렌더링 엔진)과 KJS(JavaScript 엔진)을 기반으로 2002년부터 개발되었다.

웹 브라우저에서 웹 페이지를 렌더링하기 위해 사용되며, HTML, CSS, JavaScript 등을 해석하여 사용자가 볼 수 있는 형태로 화면에 렌더링한다.

2003년 Safari 브라우저 출시와 함께 Webkit을 공식적으로 발표했으며, 2005년 오픈소스화하여 현재까지 애플 생태계 전반에 걸쳐 기본 렌더링 엔진으로 사용된다.

Webkit의 구성 요소는 다음과 같다.

WebCore – HTML, CSS, SVG, 이미지 등의 렌더링과 관련된 부분을 처리하는 핵심 렌더링 엔진

JavaScriptCore(Nitro 엔진) – JavaScript 코드를 해석하고 실행하는 엔진으로 성능이 개선된 Nitro 엔진이 주로 사용됨. Webkit을 사용하는 브라우저는 기본적으로 별도의 JavaScript 엔진이 필요없음

Web Inspector – 내장 디버깅 도구로 DOM, css, 네트워크 ㅇㅎ청 등의 분석과 디버깅이 가능

플랫폼 특정 코어 – 운영 체제와 엔진을 연결하거나 플랫폼 간의 차이를 추상화, 특정 플랫폼에서의 성능 최적화 등을 담당

Webkit의 특징으로는 웹 표준을 준수하여 최신 웹 표준을 지원하며 지속적인 최적화를 통해 성능과 에너지 효율성이 강화되었다. 특히 모바일 기기에서 배터리 소모 최소화에 중점을 둔다.

초기부터 경량화된 구조와 빠른 렌더링 속도가 장점이며 높은 에너지 효율성과 함께 애플 생태계에 최적화된 성능과 안정성을 보여준다.

그러나 애플 중심 개발과 강한 통제로 인해 애플 생태계 외에서는 기술 채택이 더디며 타플랫폼의 기여가 제한적이고 점유율이 낮다.

Blink

2013년 구글이 Webkit을 fork하여 만든 렌더링 엔진이다. Chrome 브라우저도 초기에는 Webkit을 사용했지만 아키텍쳐와 개발 방식이 맞지 않아 Blink를 개발하게 되었다.

초기 버전은 상당히 많은 부분의 코드를 공유했지만 독자적인 개발 노선을 걷기 시작하고 멀티 프로세스 아키텍쳐에 집중하여 다양한 운영 체제와 디바이스에서 원활히 작동하도록 설계되었다.

Chromium(구글 주도 오픈소스 웹 브라우저 프로젝트)은 Blink 엔진을 사용하므로 Chromium을 기반으로 하는 브라우저는 모두 Blink 렌더링 엔진을 사용한다.

Blink의 주요 구성 요소는 다음과 같다.

DOM core – HTML 파싱과 DOM 트리 생성 및 조작 지원

Layout&Render Engine – 레이아웃 계산 및 렌더 트리 생성

CSS Parser&Style Engine – CSS 파싱 및 스타일 계산

DevTools – 개발자용 디버깅 및 성능 분석 도구

참고로 Blink는 내부에 JavaScript 엔진을 포함하지 않고 외부 엔진인 V8 엔진을 사용한다.

특징으로는 멀티 프로세스 모델과 통합되어 각 탭이 독립적으로 실행되므로 보안이 강화된다. 렌더링 성능 향상을 위해 GPU를 적극 사용하고 멀티 프로세스 구조로 빠른 성능과 광범위한 생태계가 장점이다.

시장 점유율이 집중화되면서 경쟁이 줄고 웹 기술 발전이 특정 기업에 의존 경향을 보이는 것과 메모리, CPU 사용량이 많아 리소스 소모가 크고 해당 생태계에 속한 브라우저의 독립성이 감소하는 단점이 있다.

Gecko

1997년 Netscape에서 개발을 시작하였으며, 2004년 Firefox의 핵심 엔진으로 채택되었다. 2017년 Quantum 프로젝트를 통해 멀티스레드 지원, GPU 활용, 웹 표준 강화 등을 강화했다.

주요 구성 요소로는 HTML parser, CSS parser, Rendering Engine 등이 있으며, Gecko에 통합된 JavaScript 엔진은 SpiderMonkey를 사용하며 개발자 도구인 Developer Tools도 제공한다.

특징으로는 Servo 프로젝트 기술 통합을 통해 Stylo CSS 엔진을 도입하고 멀티스레드 렌더링을 지원하며 GPU 가속 활용이 강화되었다. 강력한 개인정보 보호 및 확장성이 장점이지만 낮은 시장 점유율과 Blink보다 리소스 사용량이 많은 것이 단점이다.


출처
Chromium Documentation
Google Developers Blog
Webkit Official
Mozilla Developer Network(MDN)

맥 nvm 14 버전 설치 오류 해결(nvm install 14)

apple silicon,nvm node 버전 14 설치하기

비교적 오래된 프로젝트에서는 호환성 문제로 인해 노드 버전을 낮춰서 작업하는 상황이 발생한다.

이 때 NVM을 사용하면 편리하게 노드 버전을 변경할 수 있다.

하지만 특정 버전(특히 node 14)은 설치가 되지 않고 에러 메시지가 끝없이 올라가는 상황이 발생한다.

이 때는 아키텍쳐(맥 실리콘, M1, M2, M3 등)이 원인인 상황이 많으므로 로제타2(Rosetta2)를 사용해 아키텍쳐를 x86_64로 전환해야 한다.

먼저 로제타2가 설치되어 있는지 확인하기 위해 다음 커맨드를 입력한다.

$ /usr/bin/pgrep oahd

프로세스 ID가 반환되면 이미 설치되어 있는 상태이다.

설치되어 있지 않다면 먼저 로제타2를 설치한다.

로제타2 설치 방법 (애플 서포트 페이지)

이제 터미널에서 다음 커맨드를 입력해보자.

$ arch

arm64가 출력되면 다음 커맨드를 사용해 x86_64로 전환한다.

arch -x86_64 zsh

다시 arch 커맨드를 입력해보면 변환된 아키텍쳐가 반환되는 것을 확인할 수 있다.

이제 nvm install 14를 문제없이 설치할 수 있다.

bash에서 vim 설치(feat.한글 설정)

bash: vim: command not found

경량화를 추구하는 컨테이너에는 기본 에디터가 제공되지 않으므로 필요 시 직접 설치해야 한다.

간단하게 bash에서 vim 에디터를 설치하는 방법과 한글 설정(UTF-8, CP949)까지 알아보자.

1. vim 에디터 설치

$ apt-get update

Hit:1 http://deb.debian.org/debian bookworm InRelease
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
Hit:3 http://deb.debian.org/debian-security bookworm-security InRelease
$ apt install vim

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libsodium23 vim-common vim-runtime xxd
Suggested packages:
  ctags vim-doc vim-scripts
The following NEW packages will be installed:
  libsodium23 vim vim-common vim-runtime xxd
0 upgraded, 5 newly installed, 0 to remove and 40 not upgraded.
Need to get 8962 kB of archives.
After this operation, 41.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] 

bash에서 두 커맨드를 실행하고 y를 눌러주면 끝이다(권한 문제가 발생하면 sudo를 앞에 붙인다).

그런데 한글이나 일본어 등을 사용하려면 인코딩이 필요하다.

UTF-8을 설정해보자.

vim 인코딩 설정(UTF-8)

설치한 vim을 사용해 /etc/vim/vimrc을 열고 하단에 다음 내용을 추가한다.

" Source a global configuration file if available
if filereaedable("/etc/vim/vimrc.local")
  source /etc/vim/vimrc.local
endif

//추가하는 부분
set encoding=utf-8
set fileencodings=utf-8,cp949

utf-8은 mac, cp949는 windows에서 사용하는 인코딩 방식이다.

저장하면 vim에서 한글 등이 사람 언어로 표시된다.

웹스톰(Webstorm)에서 prettier 활성화하기

웹스톰에서 prettier를 설정하는 방법

웹스톰(webstorm)에는 기본적으로 prettier가 설치되어 있습니다.

그러므로 npm 또는 yarn을 통해서 node_modules에 prettier를 설치해주고 prettier관련 설정만 해주면 됩니다.

npm install --save-dev --save-exact prettier

위와 같이 설치해준 뒤 File -> Settings -> Languages & Frameworks -> JavaScript -> Prettier에 들어가서 다음과 같이 설정해줍니다.

Prettier package에는 node_modules/prettier가 위치하는 주소를 지정하고 아래 체크 박스를 모두 체크해주면 저장 시에도 prettier가 작동이 됩니다.

작동이 안될 때는 웹스톰을 재시작.

prettier 작업의 단축키는 alt+ctrl+shift+p 입니다.

leaflet, 반복되는 지도에 marker 표시하기(react)

맵 축소 시 반복되는 지도에 Marker 반영하기

다른 옵션을 설정하지 않는 한 맵을 최대로 축소하면 다음과 같이 지도가 반복되어 나타납니다.

여기서 맵을 오른쪽이나 왼쪽으로 넘겨서 중심을 바꿔도 Marker는 그대로 있습니다.

하지만 맵 렌더링 시 다음과 같이 ‘worldCopyJump’ 옵션을 넣어주면 중심이 이동하더라도 기존의 Marker를 모두 표시할 수 있습니다.

<MapContainer
   center={[35.102, 129.067]}
   zoom={5}
   scrollWheelZoom={true}
   worldCopyJump
>

옵션 하나만으로 맵을 이동하면 Marker도 이동하여 같은 좌표에 표시되는 것을 확인할 수 있습니다.

leaflet 맵 표시 언어 변경

지도 데이터 서버 변경하기

leaflet의 기본 맵은 각 지역마다 현지 나라의 언어로 표기되어 한국 맵은 한국어, 일본 맵은 일본어, 프랑스 맵은 프랑스어로 표기되어 있습니다.

하지만 전체 맵을 영어로 표기하고 싶거나 산맥, 해양 등 용도에 맞게 지도의 이미지를 변경하고 싶을 때는 아래 링크에서 원하는 맵의 유형과 서버를 확인하여 서버만 변경해주면 됩니다.

1. 링크에서 서버 확인

http://leaflet-extras.github.io/leaflet-providers/preview/

링크에 접속하면 다음과 같은 화면입니다.

초록색 네모칸에서 서버 정보, 빨간색 네모칸에서 맵의 종류 샘플을 볼 수 있습니다.

샘플로 OpenStreetMap.France를 적용해보도록 하겠습니다.

빨간 네모칸에서 OpenStreetMap.France을 선택하면 초록 네모칸에 서버 정보가 표시됩니다.

‘https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png’

‘&copy; OpenStreetMap France | &copy; <a href=”https://www.openstreetmap.org/copyright”>OpenStreetMap</a> contributors’

이 두 부분만 코드에서 변경해주면 바로 적용이 됩니다.

2. 코드 적용

import { MapContainer, TileLayer, useMap, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import { icon } from "leaflet";
const Icon = icon({
  iconUrl: "marker-icon.png",
  iconSize: [16, 16],
  iconAnchor: [12, 16],
});

const MyMap = () => {
  return (
    <MapContainer
      center={[37.56675, 126.97842]}
      zoom={10}
      scrollWheelZoom={true}
      style={{ width: "500px", height: "500px" }}
    >
      <TileLayer
        attribution='&copy; OpenStreetMap France | &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png"
      />
      <Marker position={[37.56675, 126.97842]} icon={Icon}>
        <Popup>서울시청이에요.</Popup>
      </Marker>
    </MapContainer>
  );
};

export default MyMap;

설정에 따라 변경된 맵과 언어를 확인할 수 있습니다.

맥 OS(M1)에서 mongoDB 설치(zsh: command not found: mongo 해결)

zsh에 환경변수 설정하기

brew가 설치되어 있는 상황에서 진행합니다.

혹시 설치가 되어 있지 않은 경우에는 ‘M1 homebrew’를 검색하면 많은 안내 자료가 나오므로 참고하시면 됩니다.

먼저 설치 가능한 리스트를 확인합니다.

$ brew search mongodb

위 명령어를 실행하면 다음과 같은 리스트를 확인할 수 있습니다.

tap 명령어를 사용하면 더 많은 리스트를 확인할 수 있습니다.

$ brew tap mongodb/brew

그리고 다시 brew search mongodb를 실행하면 더 확장된 것을 볼 수 있습니다.

여기서 원하는 버전을 선택해서 설치를 진행하면 됩니다.

4.2 버전을 설치하도록 해보겠습니다.

$ brew install mongodb-community@4.2

설치가 완료되었으니 먼저 start로 몽고DB를 시작해 보겠습니다.

$ brew services start mongodb/brew/mongodb-community@4.2

Successfully started 메시지가 나오면 성공입니다.

이제 DB에 접속하기 위해 mongo를 입력해 보겠습니다.

커맨드를 찾을 수 없다는 에러가 나오는데요.

위를 살펴보면 If you need to have~~~~~ 부분에서 처음 시작하는 자는 다음 명령어를 실행하라고 나옵니다.

$ echo 'export PATH="/opt/homebrew/opt/mongodb-community@4.2/bin:$PATH"' >> ~/.zshrc

실행하고 다시 mongo를 실행해도 같은 에러가 발생하는 경우가 있습니다.

이 때는 환경변수 설정만 하고 적용이 안된 상태라서 발생하는 문제인데요.

환경변수를 적용하기 위해 다음 명령어를 실행하면 해결됩니다.

$ source ~/.zshrc

그리고 실행하면 다음과 같이 접속되는 것을 확인할 수 있습니다.

만약 이 환경변수를 직접 수정하고 싶은 경우에는 에디터를 사용해 ~/.zshrc를 열면 됩니다.

vi 에디터를 사용해 zsh(Z shell)의 환경변수 파일을 열어보겠습니다.

$ vi ~/.zshrc

앞에서 설정한 path가 들어있는 것을 볼 수 있습니다.

여기에 원하는 환경변수를 입력하거나 수정하고 저장(ESC + :wq + ENTER)해주시면 됩니다.

그리고 꼭! source ~/.zshrc를 사용해 변경을 적용을 해줘야 환경변수가 작동하므로 참고해주세요!

MongoDB, lean을 사용한 속도 개선(mongoose)

쿼리에 lean() 추가를 통한 성능 개선

몽구스(mongoose) 쿼리의 리턴값은 Document 클래스의 인스턴스입니다.

이 인스턴스는 많은 state를 갖고 있어 다양한 작업이 가능하게 합니다.

.get(), .set(), .save(), toObject(), toJSON() 등 리턴값에 대해 여러 메서드 사용이 가능하고 이 결과로 다시 쿼리를 진행할 수 있습니다.

하지만 단지 결과 데이터만 목적으로 하는 find() 같은 작업은 다른 정보나 메서드를 사용하지 않습니다.

이 때 lean()을 유용하게 사용할 수 있습니다.

쿼리에 lean()을 추가하면 인스턴스가 아닌 POJO(Plain Old Javascript Object)를 리턴합니다.

따라서 필요 없는 데이터를 함께 반환하지 않으니 속도와 메모리 부분에서 큰 장점을 발휘합니다.

샘플 코드를 통해 결과를 확인해 보겠습니다.

import sizeof from 'object-sizeof';

const query = {'status':1};
const lean = await Product.find(query).lean();
const normal = await Product.find(query).exec();

console.log('lean: '+sizeof(lean));
console.log('-----------');
console.log('normal: '+sizeof(normal));

위에서 lean과 normal의 크기를 비교한 결과는 다음과 같습니다.

lean 하나로 객체의 사이즈가 약 10배가 넘게 차이 나는 결과가 발생합니다.

하지만 lean을 사용한 결과값은 .save(), .get() 등의 사용이 불가하니 필요에 따라서 사용해야 하는 점을 유의해야 합니다.

Faster Mongoose Queries With Lean



성능 개선은 뛰어난 안목과 분석력이 있어야만 가능한 것이 아니라 작은 부분 하나하나가 만들어내는 차이를 쌓아가는 부분이라고 생각합니다.

Moment.js, A Simple Tool For Calculating Date And Time(feat.Nodejs)

Easy way to calculate date and time way better

Sometimes we need to calculate date and time.

Actually more than sometimes.

And this library, moment.js, is so powerful for your purpose.

Getting date, setting a date format whatsoever you want, subtracting date from date, counting days, and others.

Below listed some functions for your quick use.

Let’s dig it.


Install moment.js

Install library with below command.

npm install moment

Import the library with ‘require’ function.

var moment = require('moment');
moment();

//ES6 syntax
import moment from 'moment';
moment();

Let’s get started from parsing date.

const date = moment(""); //2022-01-23T11:15:00+09:00

We can display date using format() method with below tokens.

tokenmeanexample
YY(YY) year ex) YYYY -> 2022, YY -> 22
MM(MM) monthex) MMMM -> January, MM -> 01
DD dateex) DD -> 25
dd(dd) dayex) dd -> Tu, dddd -> Tuesday
hhhour(12)ex) hh -> 01
HH hour(24)ex) HH -> 13
mm minuteex) mm -> 07
sssecondex) ss -> 03
a am, pmex) a -> pm
Do ordinalex) Do -> 25th
//January Tu 2022, 01:07:21 pm
moment.format('MMMM dd YYYY, hh:mm:ss a'); 

//January Tuesday 2022, pm 01:17
moment.format('MMMM dddd YYYY, a hh:mm') 

// 01/25/2022
moment.format('MM/DD/YYYY'); 

isValid() method works well on it.

moment('2022-01-25','YYYY-MM-DD').isValid(); //true

moment('2022-02-30','YYYY-MM-DD').isValid(); //false

moment('My birth is 2022-1-25','YYYY-MM-DD').isValid(); //true

Also parsing every detail date is available by intuitive methods.

hour()get hour
minute()get minute
second()get second
millisecond()get millisecond
date()get date (1~31)
day()get day of week (0~6)
week()get week of year (1~53)
month()get month (0~11)
year()get year
moment(new Date).hour(); //13

moment().millisecond(); //331

moment().week(); //5

To get the difference in date, use diff() method.

const theDate = moment('2021-01-20', 'YYYY-MM-DD');
const myDate = moment('2022-01-25', 'YYYY-MM-DD');

myDate.diff(theDate, 'days');     // 5
myDate.diff(theDate, 'year');    // 1
myDate.diff(theDate, 'month');  // 12

We can use this method for counting expire date or calculate D-day.

And there is a bunch of methods this library thanks to the last long maintenance till today.

Please check official web for further infomation.

momentjs.com