[JavaScript] Module CommonJS, ES6 모듈 시스템

Module CommonJS, ES6 모듈 시스템


모듈이란 애플리케이션을 구성하는 개별적인 요소로서 재사용 가능한 코드 조각(부품)을 말한다.

일반적으로 모듈은 파일 단위로 분리되어 있으며 애플리케이션은 필요에 따라 명시적으로 모듈을 로드하여 재사용한다. 

즉, 모듈은 애플리케이션에 분리되어 개별적으로 존재하다가 애플리케이션의 로드에 의해 비로소 애플리케이션의 일원이 된다. 

모듈은 기능별로 분리되어 작성되므로 코드의 단위를 명확히 분리하여 애플리케이션을 구성할 수 있으며 재사용성이 좋아서 개발 효율성과 유지보수성을 높일 수 있다.



브라우저 환경에서의 모듈 시스템

브라우저 환경에서 자바스크립트는 script 태그를 사용하여 외부의 스크립트 파일을 가져와 사용할 수 있지만, 파일마다 독립적인 파일 스코프를 갖지 않고 하나의 전역 객체(Global Object)를 공유하게 된다.

그러므로 자바스크립트 파일을 여러 개의 파일로 분리하여 script 태그로 로드하여도 분리된 자바스크립트 파일들이 결국 하나의 자바스크립트 파일 내에 있는 것처럼 하나의 전역 객체를 공유한다. 

따라서 분리된 자바스크립트 파일들이 하나의 전역을 갖게 되어 전역 변수가 중복되는 등의 문제가 발생할 수 있다. 

이러한 문제점을 해결하기 위해서 script 태그에 type="module" 어트리뷰트를 추가하면 로드된 자바스크립트 파일은 모듈로서 동작하게 할 수 있긴하다.

브라우저 환경에서의 모듈 시스템을 간단히 알아보았고 본격적으로 CommonJS와 ES6 모듈 시스템에 대해서 알아보자!




CommonJS ( require / exports / module.exports )


최근 많은 프로젝트에서는 ES6 모듈 시스템을 많이 사용하지만 기존의 프로젝트들 중 CommonJS 모듈 시스템으로 작성된 코드들도 있으며 특히 Node.js에서는 CommonJS 모듈 시스템을 기본적으로 채택하고 있어 알아둘 필요가 있다.



CommonJS 모듈 시스템에서는 모듈을 불러올때 require 키워드를 사용하며,

모듈을 내보낼때는 exports 또는 module.exports 키워드를 사용한다.



내보내기

exports는 여러개의 객체를 따로따로 export 할 때 사용하고 module.exports는 한번에 export 할때 사용한다.

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

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

exports.plus = plus; // 내보내기
exports.minus = minus; // 내보내기

// 내보내기
exports.multiply = function (a, b) {
return a * b;
};

// 내보내기
exports.division = function (a, b) {
return a / b;
};



ex) module.exports
function plus(a, b) {
return a + b;
}

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

function multiply(a, b) {
return a * b;
}

function division(a, b) {
return a / b;
}

module.exports = { plus, minus, multiply, division };



무조건 여러개를 한번에 export 할때만 사용하지않고 하나만 export 할때도 사용해도 된다.

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

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

function multiply(a, b) {
return a * b;
}

function division(a, b) {
return a / b;
}

module.exports = plus;





불러오기


위에서 말했듯이 CommonJS 모듈 시스템에서는 모듈을 불러올때 require 키워드를 사용한다.

모듈을 export 하는 방식에 따라 require 하는 방식이 조금 다르다.


exports로 모듈을 하나씩 내보냈을때는 구조분해 문법을 활용하여 해당 모듈을 불러와서 사용해야 한다.


const { plus } = require('./index');


{} 객체 형식으로 해당 모듈을 불러오지 않으면 해당 모듈이 적혀있는 파일 전체를 불러오게 된다.


반면에

module.exports는 모듈을 내보내는 두가지 방식에따라 다르게 불러올 수 있다.


module.exports = { plus, minus, multiply, division };

module.exports = plus;



{} 객체 형식으로 담아서 여러개를 내보냈을 경우에는 불러올때 구조분해 문법으로 불러와야하며 

{} 객체에 담지않고 하나만 내보내는 경우 바로 불러와서 사용할 수 있다.


const plus = require('./index');








ES6 ( import / export / export default )

최근 많은 프로젝트에서는 ES6 모듈 시스템을 사용하고 있다. CommonJS에 비해 ES6 모가지는 몇가지 이점들이 있다.

우선 모듈 관리 전용 키워드를 사용하기 때문에 가독성이 좋다.

또한 비동기 방식으로 작동하고 모듈에서 실제로 사용되는 부분만 불러오기 때문에 성능과 메모리 부분에서도 유리한 측면이 있다.





내보내기

export와 export default를 사용하여 내보내기를 할 수 있다.

원하는 변수 또는 함수 앞에 export 키워드를 작성하여 각각 따로 모듈로서 내보내기가 가능하다.

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

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

export const multiply = function (a, b) {
return a * b;
};

export const division = function (a, b) {
return a / b;
};



export defualt는 하나의 객체 또는 함수 모듈로서 내보내는 경우 사용한다.

ex) export default
const plus = function (a, b) {
return a + b;
};

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

const multiply = function (a, b) {
return a * b;
};

const division = function (a, b) {
return a / b;
};

export default division;




불러오기

import 키워드를 사용하여 내보내기한 모듈을 불러올 수 있다.


export 키워드를 사용하여 내보내기한 모듈인 경우 구조분해를 통해서 불러와야하며 내보내기한 변수명 또는 함수명으로 불러와야 한다. 

// export 내보내기
export const plus = function (a, b) {
return a + b;
};

// export 불러오기
import { plus } from '.';
('./index');


만약에 특정 파일에서 각각 내보내기한 모듈을 한번에 불러오며 특정 명칭으로 사용하고자 할 경우 아래와 같이 사용할 수 있다.


import * as calculate from './index'

calculate.plus();
calculate.minus();



반면에


export default 키워드를 사용하여 내보내기한 모듈인 경우 구조분해할 필요없이 원하는 이름 또는 키워드를 사용해서 불러올 수 있다.


// export default 내보내기
const plus = function (a, b) {
return a + b;
};

export default plus;

// export default 불러오기 방법 1
import add from '.';
('./index');

// export default 불러오기 방법 2
import plus from '.';
('./index');





추가적으로 import와 require 의 몇가지 차이점


import는 정적 임포트

require는 동적 임포트


import는 항상 파일 상단에 작성하여야 하며

require는 파일 아무데서나 사용할 수 있다.


노드 최신 문법에 require 대신에 import를

module.exports 대신에 export defualt를 사용할 수 있도록 바뀌었다.  

둘은 비슷한듯 하지만 둘은 완전히 같지 않다!




댓글