CommonJS / ES6 방식으로 Node.JS 모듈 다루기

zwundzwzig·2022년 11월 9일
0

[javascript]

목록 보기
11/13
post-thumbnail

부트캠프 프로젝트 내내 require 키워드를 활용하여 불러온 모듈을 변수에 할당했다.
하지만 늘상 vscode는 내게 ES6 방식의 불러오는 방식을 추천해줬다.
이참에 오늘은 둘의 차이점을 알아보고 멋진 개발자로 거듭나자!

const express = require("express");

위의 방식이 지금까지 사용하던 방법이고,

import express from "express";

위의 방식이 vscode 추천 방식이다. 이제 순차적으로 알아보자.

CommonJS 방식

초기 자바스크립트는 독립적으로 사용됐기 때문에 한 파일에서 기능을 수행했다. 하지만 이 언어의 파급력이 커짐에 따라 브라우저 뿐 아니라 Node.JS 같은 서버 환경에서도 사용되고 있다.
그래서 하나의 파일에서 로직을 구현할 수 없을 만큼 많은 정보가 필요하게 됐고, 모듈화 구현이 가능한 Node.JS에선 여러 라이브러리와 프레임워크를 사용해 모듈 기반 시스템을 구현하고 있다.

이중에서 CommonJS는 웹 브라우저 외부에서 모듈을 사용케하는 시스템이다. CommonJS는 Node.JS를 사용한 서버 측 JavaScript 프로그래밍에 널리 사용된다.

내보내기

특정 변수나 그 변수의 속성으로 내보낼 객체를 세팅해야 한다.

module이라는 객체 내 exports라는 키가 있는 프로퍼티를 활용해 구현한 함수나 변수를 내보낼 수 있다.

// jelly.js
const getHaribo = (haribo) => {
  return `하리보 ` + haribo + `개 주세요!`;
};

function beKind() {
  return `맛있게 드세요!`
}

function beRude() {
  return ``
}

module.exports = { getHaribo, beKind };

여기서 모듈이란 객체는 id, path, exports, filename, loaded, children, paths 등의 키를 가진다.

이중 exports 키 값에 내가 만든 함수를 넣어 내보내는 것이다!

혹은 그냥 exports 변수의 속성으로 내보낼 수도 있다.

// jelly.js
const getHaribo = (haribo) => {
  return `하리보 ` + haribo + `개 주세요!`;
};

function beKind() {
  return `맛있게 드세요!`
}

function beRude() {
  return ``
}

exports.getHaribo = getHaribo;
exports.beKind = beKind;

이런 식으로 복수의 객체로 내보낼 수 있다.

왜냐하면,

interface NodeModule extends NodeJS.Module { }

declare var module: NodeModule;

// Same as module.exports
declare var exports: any;

라고 해당 타입스크립트에 정의돼 있기 때문이다.

불러오기

2015년에 ES6가 나오기 전까지 브라우저나 서버 환경에서 자바스크립트는 이 방식으로 모듈을 불러오고 변수처럼 사용했다.

<script> 태그를 사용하는 브라우저 HTML이나, Babel처럼 ES6 코드를 변환(transpile)해주는 도구를 사용할 수 없을 때는 require 키워드를 사용해야 한다.

const { getHaribo, beKind } = require("./jelly");

console.log(getHaribo(5));
console.log(beKind());

위 방식은 module.exports로 단일 객체에 담아왔을 경우고,

const haribo = require("./jelly");

console.log(haribo.getHaribo(5));
console.log(haribo.beKind());

위 방식은 하나의 변수에 담아오는 로직이다.

ES6 방식

최신 스펙인 ES6 방식은 많은 프로젝트에서 널리 사용되고 있다.

이는 import, from, export, default처럼 모듈 관리 전용 키워드를 사용하기 때문에 가독성에 장점이 있고, 비동기 방식으로 작동하고 모듈에서 실제로 쓰이는 부분만 불러오기 때문에 성능과 메모리 부분에서 유리하다.

내보내기

// jelly.js
const getHaribo = (haribo) => {
  return `하리보 ` + haribo + `개 주세요!`;
};

export function beKind() {
  return `맛있게 드세요!`
}

function beRude() {
  return ``
}

export { getHaribo };

Named Exports

이때, 내보내는 변수 or 함수의 이름이 그대로 불러낼 때 사용하게 되는 이름이랑 같다. 이를 Named Exports라 부른다.

이렇게 내보낸 함수, 클래스를 받아오려면

import { getHaribo, beKind as soKind } from './jelly.js'

이와 같이 내보낼 때 이름을 그대로 쓰거나 as 키워드를 활용해 받아올 수 있다.

import * as haribo from './jelly.js'

또한 *를 사용해 해당 파일에 모든 함수나 클래스를 받아올 수 있다.

이 방식의 장점으로 여러 값을 내보낼 때 유용하다는 점이다.

Default Export

참고로, 이와 다른 방식의 내보내기 방법이 있는데 Default Export이며, 이 방식으론 한 파일에서 변수, 클래스, 함수 등등 중 하나만 내보낼 수 있다.

// jelly.js
const getHaribo = (haribo) => {
  return `하리보 ` + haribo + `개 주세요!`;
};

function beKind() {
  return `맛있게 드세요!`
}

function beRude() {
  return ``
}

export default getHaribo;

대신 이 방식은 불러올 때 어떤 이름으로든 받을 수 있다.

import haribo from './jelly.js'

그리고 함수 표현식 혹은 변수 선언할 때 바로 export할 수 없다.

보통 한 개의 파일이 하나의 함수나 클래스를 담고 있기 때문에 default를 자주 사용해도 될 거 같다.

불러오기

import { getHaribo, beKind } from "./jelly";

console.log(getHaribo(5));
console.log(beKind());

이외에도 기존 ES6 모듈을 사용하기 위해선 Babel과 같은 트랜스파일러(transpiler)를 사용해야 한다고 상술했다.

그러나, Node.JS v13.2부터 package.json 파일에서 "type": "module" 이라는 프로퍼티를 삽입하면 해결된다고 한다.

참조

profile
개발이란?

0개의 댓글