javascript의 module 시스템

Yeongjong Kim·2021년 9월 13일
1

Javascript에 모듈 시스템은 참 다양하다.
node.js 환경에서 사용가능한 모듈 시트템과 브라우저에서 사용가능한 모듈시스템이
구분되며, 이에 따라 헷갈리기 쉬운 모듈 개념을 정리하는 시간을 가져보려고 한다.

1. node 환경의 모듈 시스템

1.1. commonJS

Ecmascrip에서 인정한 표준 모듈은 아니지만 node.js 환경에서는 거의 표준이다 싶이 채택한 기본 모듈 시스템이다.

module.exports

function add(a, b) {
  return a + b;
}

module.exports = add;

모듈을 외부에서 사용하려면 "module" 전역 네임스페이스의 exports 프로퍼티에 값을 할당한다.

require

const add = require('./add');
console.log(add(1, 2));

require 함수의 인수로 exports한 경로를 입력하면 모듈을 불러올 수 있다.(확장자 생략 가능)

1.2. ESM

ES6(ECMA2015+) 부터 지원하는 표준 모듈 시스템이다.
node 환경에서는 package.json 파일에서 type: "module" 프로퍼티를 설정하면 그 때 부터는 모듈 시스템이 import export로 변경된다. type을 변경하게 되면 기존의 commonJS 방식은 사용할 수 없으므로 주의해서 사용해야 하자.

export

export function add(a, b) {
  return a + b;
}

ESM은 모듈을 외부에서 사용하기 위해 export 키워드를 사용한다.

default export
파일 내에 여러 개의 함수 혹은 변수들을 외부로 내보낼 수 있다. 이 때 default를 export 앞에 붙여주면, 모듈의 기본 내보내기로 설정된다.

export function plus(a, b) {
  return a + b;
}

export function minus(a, b) {
  return a - b;
}

export default function add(a, b) {
  return a + b;
}

import

import add, { plus, minus } from './add.js';
...

import 키워드로 모듈을 불러올 수 있다.
단 from 뒤의 모듈 경로는 반드시 파일의 확장자 단위까지 포함한 완전한 형태로 입력해야 한다. 생략이 불가능하다.

plus와 minus의 경우 중괄호로 감싸 있는데, 이 문법이 일반적인 export 키워드로 내보내기 한 모듈이며, add처럼 중괄호 없이 import하는 문법은 default export 키워드로 내보내기 한 모듈이다.

2. 브라우저 환경의 모듈 시스템

브라우저 환경에서는 ESM 방식만을 지원한다. 하지만 현대에는 React와 같은 프레임워크와 더불어 test 라이브러리를 node.js 환경에서 구동시키는데, 이 같은 경우 브라우저와 node.js 환경에서 지원하는 모듈 시스템이 다르기 때문에 오류가 발생할 수 있다.

이 때는 package.json 에서 type: module 프로퍼티를 설정해주면 문제가 해결되지만, ESM은 모든 모듈에 경로를 확장자까지 포함하여 기입해야해서 불편한 점이 많다.

webpack은 이런 문제를 해결하는 최상의 모듈 번들러이다. CommonJs, ESM 뿐만아니라 확장자 생략 및 다양한 커스텀 경로 설정까지 가능하기 때문에, 매우 편리하다.

import add from './add'; // import add from './add.js'
import add from './directory/'; // import add from './directory/index.js'
import { Slick } from 'components/'; // import { add } from './src/components/Slick/Slick.js'

3. webpack 활용하기

3.1. webpack 설정

ESM 방식(비권장)

package.js 에서 type을 module로 설정하여 EMS 방식으로 webpack을 사용할 수 있다.
webpack.config.js 파일을 root 경로에 만들어주고 다음과 같이 입력한다.

import path from 'path';
const __dirname = path.resolve(); // ESM 방식은 __dirname이 없다.

export default {
  // module.exports
  entry: ['./test.js'],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
};

주의할 점

  • package.json의 모듈 타입 설정에 따라 webpack 설정도 export 혹은 module.exports 문법을 따라야한다.
  • commonJS 문법의 경우 __dirname을 기본적으로 제공하지만, ESM 방식은 지원하지 않기 때문에 따로 설정해 주어야 한다.
  • ESM 문법으로 설정할 경우, 무조건 ESM 문법만을 따라야 하기 때문에 모듈문법을 유연하게 사용할 수 있는 webpack의 장점을 살릴 수 없다.

권장 설정

  1. node.js 의 기본 모듈 설정인 commonJS를 따른다.
  2. import export 문법을 사용하여 모듈을 유연하게 로드한다.
  3. webpack은 js를 번들할 때, 내부적으로 브라우저가 사용가능한 모듈 문법으로 변환해준다.
  4. babel을 사용하여 크로스 브라우징을 한다.

3.2. jest 설정

위와같이 webpack 모듈 방식을 사용할 경우, require문을 사용하지 않으면 jest 실행시 SyntaxError가 발생한다. jest가 node 환경에서 실행되니 당영한 결과다.

이럴 경우에는, 루트경로에 .babelrc 파일을 따로 만들어서 node.js 환경에서 실행될 때는 별도의 모듈 시스템이 적용되도록 분리할 수 있다.

{
  "presets": [
    ["@babel/preset-env", {
      "loose": true,
      "modules": "commonjs", // <= 이부분이 중요하다. auto 혹은 commonjs로 설정
      "targets": [
        "defaults",
        "> 1% in KR",
        "not dead", // 1년이상 브라우저 관리가 되지 않은 것 dead라고 판단.
        "ie 10"
      ]
    }]
  ]
}
profile
Front 💔 End

0개의 댓글