티스토리 뷰

date-fns 는 많은 JS 날짜 관련 라이브러리 중 tree shaking을 지원하고 fucntional pattern으로 동작하는 라이브러리이다. 

yarn add date-fns

위의 명령어를 통해 내 프로젝트에 date-fns를 설치해준다. 

  • date-fns도 moment.js나 day.js처럼 date-fns 모듈 객체를 불러와서 사용이 가능하다.
  • 위의 두 가지 라이브러리와 다르게 tree shaking 지원, functional하게 사용 가능하다는 장점이 있다.
  • 장점을 살려 사용에 필요한 함수를 import하여 사용하는 것이 불필요한 함수에 용량을 사용하지 않을 수 있다. 
//logger.js

const { format } = require("date-fns"); //159.7k
// v4를 uuid로 rename
const { v4: uuid } = require("uuid"); // 4.1k
const fs = require("fs");
const fsPromises = require("fs").promises;
const path = require("path");

const logEvents = async (message, logFileName) => {
  const dateTime = `${format(new Date(), "yyyyMMdd\tHH:mm:ss")}`;
  const logItem = `${dateTime}\t${uuid()}\t${message}\n`;

  try {
    if (!fs.existsSync(path.join(__dirname, "..", "logs"))) {
      await fsPromises.mkdir(path.join(__dirname, "..", "logs"));
    }
    await fsPromises.appendFile(
      path.join(__dirname, "..", "logs", logFileName),
      logItem
    );
  } catch (err) {
    console.log(err);
  }
};

const logger = (req, res, next) => {
  logEvents(`${req.method}\t${req.headers.origin}\t${req.url}`, "reqLog.txt");
  console.log(`${req.method} ${req.path}`);
  next();
};

module.exports = { logEvents, logger };

위의 코드에서 보면, require를 통해 date-fns의 format 함수를 가져왔다. 트리셰이킹을 지원한다고했는데 생각보다 너무 사이즈가 커서 이게 트리셰이킹된건가 의아했다. require 밑줄에 ...표시가 있어서 마우스로 안내 메세지를 확인해보니 

File is a CommonJS module; it may be converted to an ES module. ts(80001)

라는 에러 메세지를 받을 수 있었다. CommonJS 모듈 시스템으로는 트리셰이킹이 되지 않는 모양이다. 

 

아래와 같이 CommonJS 모듈 -> ES 모듈 방식으로 변경해주었더니 트리셰이킹이 된다.

하지만 node.js로 작업을하고 있는 중이라서 트리셰이킹은 사용하지 못할 듯하다. (그러면 굳이 이걸 왜 노드에서써야하지..)

import { format } from "date-fns" //23.7k

기존 Date객체와 비교했을 때에도 큰 필요성이 안 느껴져서 굳이 사용하지 않아도 될 거 같은 라이브러리같다는 생각이 들었다. 

 

Node.js는 ES module을 못쓰나?

물론 백엔드에서도 ES module 시스템을 사용할 수 있지만 Node.js의 경우는 모듈 시스템에 대한 기본값으로 CommonJS를 사용하므로 모든 파일이 ES module을 사용하도록 설정하기위한 추가 구성이 필요하다. 

파일 확장자를 .mjs로 변경하거나 package.json파일에서 "type":"module" 을 설정하면 된다. 그러나 이런 설정을 사용하면 기존의 CommonJS모듈을 불러오는 방식이 변경될 수 있으므로, 이를 고려하여 코드를 수정해야 한다. 

 


모듈

어플리케이션을 구성하는 개별적 요소로서 재사용 가능한 코드 조각을 말한다.

분리한 코드조각을 각각의 모듈이라고 부른다. 

 

라이브러리도 모듈의 일부이며 내가 작성한 함수도 하나의 모듈이 될 수 있다.

자바스크립트는 파일마다 독립적인 파일 스코프를 가지고 있지 않고 하나의 전역객체를 공유하여 사용한다. 전역변수가 중복되는 등의 문제가 발생할 수 있다. 즉 여러 개의 파일로 분리하여 여러 개의 script 태그를 사용하여도 이는 모듈화로 볼 수 없다. 

// script 1, 2, 3 은 모두 같은 전역 스코프를 공유한다.
<script src="script1.js />
<script src="script2.js />
<script src="script3.js />

이러한 문제점을 해결하기 위해 Node.js에서는 표준이라할 수 있는 CommonJS를 채택했다. 

이렇게 함으로써 모듈은 각자의 스코프를 가지게 된다. 

그러나, 브라우저(클라이언트 사이드 자바스크립트)에서는 이를 지원하지 않았다. 그래서 ES6에서 이를 해결하기 위해 모듈 기능이 추가된 것이다. 

ES Module (MJS)

  • 모듈로더를 비동기 환경에서 실행하고, import export 구문을 찾아서 파싱한다.
  • 더이상 import 할 값이 없을 때까지 import를 찾는다.
  • 스크립트들이 실행된다. 
  • package.config의 type:module로 set해주어야 한다.(기본값 x)

Common JS (CJS)

  • default값
  • require()는 동기로 이루어진다. promise나 callback을 return하지 않는다.
  • 즉, require 내부의 script를 실행하고 export 되어있는 값을 return 한다.

 

댓글