본문 바로가기

Javascript Module

web/javascript by 낼스 2019. 7. 12.

Javascript Module


※ 참고 : https://github.com/codepink/codepink.github.com/wiki/자바스크립트-모듈,-모듈-포맷,-모듈-로더와-모듈-번들러에-대한-10분-입문서

# 자바스크립트 모듈
             모듈 포맷
             모듈 로더
             모듈 번들러

    - 코드 추상화 : 특수한 라이브러리에 기능을 위임하여 실제 구현의 복잡도를 이해할 필요가 없다.
    - 코드 캡슐화 : 코드를 변경하지 않으려면 모듈 내부에 코드를 숨긴다.
    - 코드 재사용 : 같은 코드를 반복해서 작성하는 것을 피한다.
    - 의존성 관리 : 코드를 다시 작성하지 않고도 쉽게 의존성을 변경한다.

# 노출식 모듈 패턴
    :: 즉시 실행 함수 표현식(IIFE : Immediately Invoked Function Expression)
        (function(){
          // ...
        })()

    :: 노출식 모듈 패턴
        // Expose module as global variable
        var singleton = function(){

          // Inner logic
          function sayHello(){
            console.log('Hello');
          }

          // Expose API
          return {
            sayHello: sayHello
          }
        }();

        // === execute
        // Access module functionality
        singleton.sayHello();
        // => Hello

    :: 싱글톤 대신 함수 생성자를 이용하는 방법.
        // Expose module as global variable
        var Module = function(){

          // Inner logic
          function sayHello(){
            console.log('Hello');
          }

          // Expose API
          return {
            sayHello: sayHello
          }
        }

        // === execute
        var module = new Module();
        module.sayHello();
        // => Hello

    :: 노출식 모듈 패턴 결론
        1. IIFE의 장점을 이용하지만, 
        2. 의존성에대한 관리는 불가능함.

# 모듈 포맷 : 모듈을 정의하기위한 문법
    :: EcmaScript6 , ES2015 이전에는 모듈을 정의하기위한 공식적인 문법이 정의되지 않음.

    :: 포맷
        - 비동기 모듈 정의(AMD, Asynchronous Module Definition)
        - CommonJS
        - 만능 모듈 정의(UMD, Universal Module Definition)
        - System.register
        - ES6 모듈 포맷


    :: 비동기 모듈 정의(AMD) ( https://github.com/amdjs/amdjs-api/wiki/AMD )
        ::: AMD 포맷은 브라우저에서 사용되고 define 함수를 사용해서 모듈을 정의한다.
        //Calling define with a dependency array and a factory function
        define(['dep1', 'dep2'], function (dep1, dep2) {

          //Define the module value by returning a value.
          return function () {};
        });

    :: CommontJS 포맷 ( http://www.commonjs.org )
        ::: CommonJS 포맷은 Node.js에서 사용되고,
            require와 module.exports를 사용해서 의존성과 모듈을 정의한다.

        var dep1 = require('./dep1');  
        var dep2 = require('./dep2');

        module.exports = function(){  
          // ...
        }

    :: 만능 모듈 정의(UMD) ( https://github.com/umdjs/umd )
        ::: UMD 포맷은 브라우저와 Node.js에서 둘 다 사용될 수 있다.

        (function (root, factory) {
          if (typeof define === 'function' && define.amd) {
            // AMD. Register as an anonymous module.
            define(['b'], factory);
          } else if (typeof module === 'object' && module.exports) {
            // Node. Does not work with strict CommonJS, but
            // only CommonJS-like environments that support module.exports,
            // like Node.
            module.exports = factory(require('b'));
          } else {
            // Browser globals (root is window)
            root.returnExports = factory(root.b);
          }
        }(this, function (b) {
          //use b in some fashion.

          // Just return a value to define the module export.
          // This example returns an object, but the module
          // can return a function as the exported value.
          return {};
        }));

    :: System.register ( https://github.com/ModuleLoader/es-module-loader/blob/master/docs/system-register.md )
        import { p as q } from './dep';

        var s = 'local';

        export function func() {  
          return q;
        }

        export class C {  
        }

# ES6 모듈 포맷
    - ES6에서 자바스크립트는 내장된 모듈 포맷도 지원한다.
    - 모듈의 공개 API로 내보내기 위해 export 토큰을 사용한다.

    // lib.js

    // Export the function
    export function sayHello(){  
      console.log('Hello');
    }

    // Do not export the function
    function somePrivateFunction(){  
      // ...
    }
    그리고 import 토큰은 모듈이 내보내는 부분을 가져온다.

    import { sayHello } from './lib';

    sayHello();  
    // => Hello
    우리는 as를 사용하여 가져오는 모듈에 별명을 줄 수도 있다.

    import { sayHello as say } from './lib';

    say();  
    // => Hello
    또는 전체 모듈을 한 번에 로드할 수도 있다.

    import * as lib from './lib';

    lib.sayHello();  
    // => Hello
    이 형식은 default export도 지원한다. (역자주: default export를 사용하면 모듈을 가져올 때 괄호({})를 사용하지 않아도 되며, 단일 값을 내보낼 때 사용한다)

    // lib.js

    // Export default function
    export default function sayHello(){  
      console.log('Hello');
    }

    // Export non-default function
    export function sayGoodbye(){  
      console.log('Goodbye');
    }
    모듈은 다음과 같이 가져온다.

    import sayHello, { sayGoodbye } from './lib';

    sayHello();  
    // => Hello

    sayGoodbye();  
    // => Goodbye
    함수뿐만 아니라 어떤 것이든 내보낼 수 있다.

    // lib.js

    // Export default function
    export default function sayHello(){  
      console.log('Hello');
    }

    // Export non-default function
    export function sayGoodbye(){  
      console.log('Goodbye');
    }

    // Export simple value
    export const apiUrl = '...';

    // Export object
    export const settings = {  
      debug: true
    }
    불행하게도 내장된 모듈 포맷은 아직 모든 브라우저에서 지원되지 않는다.

    그래서 우리는 이미 ES6 모듈 포맷을 사용할 수 있지만, 
    
    브라우저에서 코드를 실행하기 전에 Babel과 같은 변환기를 사용해 ES5 모듈 포맷(AMD 또는 CommonJS)으로 코드 변환이 필요하다.


# 모듈 로더
    모듈 로더는 주요 모듈 포맷으로 작성된 모듈을 해석하고 로드한다.

    모듈 로더는 런타임에 실행된다.

    브라우저에서 모듈 로더를 로드한다.
    모듈 로더에게 어떤 메인 애플리케이션 파일을 로드할 것인지 알려준다.
    모듈 로더는 메인 애플리케이션 파일을 다운로드하고 해석한다.
    필요한 경우 모듈 로더가 파일을 다운로드한다.
    브라우저 개발자 콘솔에서 네트워크 탭을 열면, 모듈 로더에 의해 많은 파일들이 로드된 것을 볼 수 있다.

    인기 있는 모듈 로더에는 다음과 같은 것들이 있다.

    RequireJS : AMD 포맷 모듈을 위한 로더 : https://requirejs.org/
    SystemJS : AMD, CommonJS, UMD 또는 System.register 포맷 모듈을 위한 로더 : https://github.com/systemjs/systemjs


# 모듈 번들러
    모듈 번들러는 모듈 로더를 대체한다.

    모듈 로더와 반대로 모듈 번들러는 빌드 타임에 실행된다.

    빌드 타임에 번들 파일을 생성하기 위해 모듈 번들러를 실행한다. ( 예: bundle.js )
    브라우저에서 번들 파일을 로드한다.
    브라우저 개발자 콘솔에서 네트워크 탭을 열면,
    모듈 로더에 의해 1개 파일만 로드된 것을 볼 수 있다.
    브라우저에서 모듈 로더를 필요로 하지 않는다.
    모든 코드는 번들 안에 포함되어 있다.

    인기 있는 모듈 번들에는 다음과 같은 것들이 있다.

    Browserify  : CommonJS 모듈을 위한 번들러           : http://browserify.org/
    Webpack     : AMD, CommonJS, ES6 모듈을 위한 번들러 : https://webpack.github.io/

# 요약
    모던 자바스크립트 개발 환경에서 툴링을 잘 이해하기 위해서는 모듈, 모듈 포맷, 모듈 로더와 모듈 번들러 사이의 차이를 이해하는 것이 중요하다.

    :: 모듈은 구현 세부 사항을 캡슐화하고 공개 API를 노출해 다른 코드에서 쉽게 로드하고 사용할 수 있도록 재사용 가능한 코드 조각이다.

    :: 모듈 포맷은 모듈을 정의하기 위해 사용하는 문법이다. AMD, CommonJS, UMD, System.register 와 같은 여러 모듈 포맷이 과거에 등장했으며, ES6부터 내장된 모듈 포맷을 사용할 수 있다.

    :: 모듈 로더는 주요 모듈 포멧으로 작성된 모듈을 런타임 때 로드하고 해석한다. RequireJS와 SystemJS가 있다.

    :: 모듈 번들러는 모듈 로더를 대체하고 빌드 타임에 모든 코드의 번들을 생성한다. Browserify와 Webpack이 있다.


================================================================================================== ※ 참고 : https://github.com/codepink/codepink.github.com/wiki/자바스크립트-모듈,-모듈-포맷,-모듈-로더와-모듈-번들러에-대한-10분-입문서 # 자바스크립트 모듈 모듈 포맷 모듈 로더 모듈 번들러 - 코드 추상화 : 특수한 라이브러리에 기능을 위임하여 실제 구현의 복잡도를 이해할 필요가 없다. - 코드 캡슐화 : 코드를 변경하지 않으려면 모듈 내부에 코드를 숨긴다. - 코드 재사용 : 같은 코드를 반복해서 작성하는 것을 피한다. - 의존성 관리 : 코드를 다시 작성하지 않고도 쉽게 의존성을 변경한다. # 노출식 모듈 패턴 :: 즉시 실행 함수 표현식(IIFE : Immediately Invoked Function Expression) (function(){ // ... })() :: 노출식 모듈 패턴 // Expose module as global variable var singleton = function(){ // Inner logic function sayHello(){ console.log('Hello'); } // Expose API return { sayHello: sayHello } }(); // === execute // Access module functionality singleton.sayHello(); // => Hello :: 싱글톤 대신 함수 생성자를 이용하는 방법. // Expose module as global variable var Module = function(){ // Inner logic function sayHello(){ console.log('Hello'); } // Expose API return { sayHello: sayHello } } // === execute var module = new Module(); module.sayHello(); // => Hello :: 노출식 모듈 패턴 결론 1. IIFE의 장점을 이용하지만, 2. 의존성에대한 관리는 불가능함. # 모듈 포맷 : 모듈을 정의하기위한 문법 :: EcmaScript6 , ES2015 이전에는 모듈을 정의하기위한 공식적인 문법이 정의되지 않음. :: 포맷 - 비동기 모듈 정의(AMD, Asynchronous Module Definition) - CommonJS - 만능 모듈 정의(UMD, Universal Module Definition) - System.register - ES6 모듈 포맷 :: 비동기 모듈 정의(AMD) ( https://github.com/amdjs/amdjs-api/wiki/AMD ) ::: AMD 포맷은 브라우저에서 사용되고 define 함수를 사용해서 모듈을 정의한다. //Calling define with a dependency array and a factory function define(['dep1', 'dep2'], function (dep1, dep2) { //Define the module value by returning a value. return function () {}; }); :: CommontJS 포맷 ( http://www.commonjs.org ) ::: CommonJS 포맷은 Node.js에서 사용되고, require와 module.exports를 사용해서 의존성과 모듈을 정의한다. var dep1 = require('./dep1'); var dep2 = require('./dep2'); module.exports = function(){ // ... } :: 만능 모듈 정의(UMD) ( https://github.com/umdjs/umd ) ::: UMD 포맷은 브라우저와 Node.js에서 둘 다 사용될 수 있다. (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['b'], factory); } else if (typeof module === 'object' && module.exports) { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. module.exports = factory(require('b')); } else { // Browser globals (root is window) root.returnExports = factory(root.b); } }(this, function (b) { //use b in some fashion. // Just return a value to define the module export. // This example returns an object, but the module // can return a function as the exported value. return {}; })); :: System.register ( https://github.com/ModuleLoader/es-module-loader/blob/master/docs/system-register.md ) import { p as q } from './dep'; var s = 'local'; export function func() { return q; } export class C { } # ES6 모듈 포맷 - ES6에서 자바스크립트는 내장된 모듈 포맷도 지원한다. - 모듈의 공개 API로 내보내기 위해 export 토큰을 사용한다. // lib.js // Export the function export function sayHello(){ console.log('Hello'); } // Do not export the function function somePrivateFunction(){ // ... } 그리고 import 토큰은 모듈이 내보내는 부분을 가져온다. import { sayHello } from './lib'; sayHello(); // => Hello 우리는 as를 사용하여 가져오는 모듈에 별명을 줄 수도 있다. import { sayHello as say } from './lib'; say(); // => Hello 또는 전체 모듈을 한 번에 로드할 수도 있다. import * as lib from './lib'; lib.sayHello(); // => Hello 이 형식은 default export도 지원한다. (역자주: default export를 사용하면 모듈을 가져올 때 괄호({})를 사용하지 않아도 되며, 단일 값을 내보낼 때 사용한다) // lib.js // Export default function export default function sayHello(){ console.log('Hello'); } // Export non-default function export function sayGoodbye(){ console.log('Goodbye'); } 모듈은 다음과 같이 가져온다. import sayHello, { sayGoodbye } from './lib'; sayHello(); // => Hello sayGoodbye(); // => Goodbye 함수뿐만 아니라 어떤 것이든 내보낼 수 있다. // lib.js // Export default function export default function sayHello(){ console.log('Hello'); } // Export non-default function export function sayGoodbye(){ console.log('Goodbye'); } // Export simple value export const apiUrl = '...'; // Export object export const settings = { debug: true } 불행하게도 내장된 모듈 포맷은 아직 모든 브라우저에서 지원되지 않는다. 그래서 우리는 이미 ES6 모듈 포맷을 사용할 수 있지만, 브라우저에서 코드를 실행하기 전에 Babel과 같은 변환기를 사용해 ES5 모듈 포맷(AMD 또는 CommonJS)으로 코드 변환이 필요하다. # 모듈 로더 모듈 로더는 주요 모듈 포맷으로 작성된 모듈을 해석하고 로드한다. 모듈 로더는 런타임에 실행된다. 브라우저에서 모듈 로더를 로드한다. 모듈 로더에게 어떤 메인 애플리케이션 파일을 로드할 것인지 알려준다. 모듈 로더는 메인 애플리케이션 파일을 다운로드하고 해석한다. 필요한 경우 모듈 로더가 파일을 다운로드한다. 브라우저 개발자 콘솔에서 네트워크 탭을 열면, 모듈 로더에 의해 많은 파일들이 로드된 것을 볼 수 있다. 인기 있는 모듈 로더에는 다음과 같은 것들이 있다. RequireJS : AMD 포맷 모듈을 위한 로더 : https://requirejs.org/ SystemJS : AMD, CommonJS, UMD 또는 System.register 포맷 모듈을 위한 로더 : https://github.com/systemjs/systemjs # 모듈 번들러 모듈 번들러는 모듈 로더를 대체한다. 모듈 로더와 반대로 모듈 번들러는 빌드 타임에 실행된다. 빌드 타임에 번들 파일을 생성하기 위해 모듈 번들러를 실행한다. ( 예: bundle.js ) 브라우저에서 번들 파일을 로드한다. 브라우저 개발자 콘솔에서 네트워크 탭을 열면, 모듈 로더에 의해 1개 파일만 로드된 것을 볼 수 있다. 브라우저에서 모듈 로더를 필요로 하지 않는다. 모든 코드는 번들 안에 포함되어 있다. 인기 있는 모듈 번들에는 다음과 같은 것들이 있다. Browserify : CommonJS 모듈을 위한 번들러 : http://browserify.org/ Webpack : AMD, CommonJS, ES6 모듈을 위한 번들러 : https://webpack.github.io/ # 요약 모던 자바스크립트 개발 환경에서 툴링을 잘 이해하기 위해서는 모듈, 모듈 포맷, 모듈 로더와 모듈 번들러 사이의 차이를 이해하는 것이 중요하다. :: 모듈은 구현 세부 사항을 캡슐화하고 공개 API를 노출해 다른 코드에서 쉽게 로드하고 사용할 수 있도록 재사용 가능한 코드 조각이다. :: 모듈 포맷은 모듈을 정의하기 위해 사용하는 문법이다. AMD, CommonJS, UMD, System.register 와 같은 여러 모듈 포맷이 과거에 등장했으며, ES6부터 내장된 모듈 포맷을 사용할 수 있다. :: 모듈 로더는 주요 모듈 포멧으로 작성된 모듈을 런타임 때 로드하고 해석한다. RequireJS와 SystemJS가 있다. :: 모듈 번들러는 모듈 로더를 대체하고 빌드 타임에 모든 코드의 번들을 생성한다. Browserify와 Webpack이 있다. Javascript Module

'web > javascript' 카테고리의 다른 글

node javascript async parallel  (0) 2019.07.12
node javascript async series  (0) 2019.07.12
Javascript arrow function expression  (0) 2019.07.12
Replace Tag(Script & div & B tag to strong)  (0) 2019.07.12
bind click event loop index  (0) 2019.07.12

댓글