JavaScript 모듈화 및 Lazy Loading 으로 쓰이는 기술, AMD에 대해 간단히 알아보자


동적로딩(Dynamic Loading, Lazy Loading)

  • HTML 파일 로딩시에 <script> 태그내의 내용이 모두 로딩되기전까지 html 이 파싱되지 않고 기다리고 있어서 페이지의 랜더링이 늦어진다.
    • 꼼수로 <body> 태그의 마지막에 <script> 태그를 배치하여 UI 랜더링이후 <script> 내용을 읽는 방법이 있다.
  • 동적로딩은 필요할 경우에만 <script> 내용을 동적으로 로딩하는 방법으로, Eclipse 의 plug-in 시스템과 비슷한 맥락의 방법이다.
    • 동적로딩은 여러 방법이 있지만 <script> 태그를 동적으로 만들어서 헤더태그의 제일 마지막에 삽입하는 방법이 많이 쓰인다.
  • 예제
    • <!-- index.html --!>
      <html>
       <head>
              <title>Test</title>
              <script src="js/main.js"></script>
          </head>
          <body>
              <button onclick="test()">Lazy Loading</button>
          </body>
      </html>
      
    • // main.js
      function test() {
          var scriptElement = document.createElement('script');
          scriptElement.type = 'text/javascript';
          scriptElement.src = 'js/lazy.js';
          scriptElement.onload = function(script) {
              console.log('script lodaed!');
          };
          document.getElementsByTagName('head')[0].appendChild(scriptElement);
      }
      
    • // lazy.js
      function lazy() {
          alert('lazy');
      }
      
    • 실행결과
      • Lazy Loading 버튼을 클릭하기 전에는 lazy.js 가 로딩되지 않았지만, 버튼을 클릭하면 lazy.js 가 로딩이된다.


History

  • JavaScript 모듈화에 대한 명세를 정의하는 표준화 정의 그룹으로 CommonJS 그룹이 있고, 여기서 신설된 AMD 라는 그룹이 새로 생김
  • JavaScript 모듈화의 목표
    • 모듈화
      • 외부에서 쉽게 사용가능
    • Lazy Loading
      • 필요할때에 로딩 가능
    • JavaScript 에 대한 모듈정의 
      • 스코프(Scope): 모든 모듈은 자신만의 독립적인 실행 영역이 있어야 한다.
      • 정의(Definition): 모듈 정의는 exports 객체나 define 함수를 이용
      • 사용(Usage): 모듈 사용은 require 함수를 이용


CommonJS(CJS)

  • http://www.commonjs.org/
  • exports
    • 모듈 정의
  • require()
    • 모듈 사용
  • 예제
    • //--------------------------------------------- 
      // test.js
      // export 할 모듈 정의
      function test(){
          this.first = function(){
              console.log('first');
          }
          this.last = function(){
              console.log('last');
          }
      }
      // 모듈 export
      exports.test = test;
      
      //--------------------------------------------- 
      // main.js
      var test = require('./test').test;
      var module = new test(); 
      module.first(); // 'first'
      module.last(); // 'last'
      


AMD

  • https://github.com/amdjs/amdjs-api/blob/master/AMD.md
  • define()
    • 모듈 정의
    • CommonJS 의 exports 와 같은 개념
    • Signature
      • define(
            module_id /*optional*/, 
            [dependencies] /*optional*/, 
            definition function /*function for instantiating the module or object*/
        );
        
    • module_id
      • 모듈 이름
    • dependencies
      • 모듈이 갖는 의존성  모듈(먼저 로드되어야 하는 모듈)의 배열
      • 기술된 모듈은 definition function 의 인자로 순서대로 전달된다.
      • 예제
        • //--------------------------------------------- 
          // test.js
          // 모듈정의
          define([
                  'js/jquery.js', // 의존성을 가지는 모듈들을 기술
                  'js/my.js'
              ], function(jQuery, my) { // 의존성을 가지는 모듈들이 순서대로 매개변수로 담김
                  // 의존 모듈들이 모두 로딩 완료되면 함수를 실행
                  function first() {
                      console.log('first');
                  }
                  function last() {
                      console.log('last');
                  }
                  return {
                      first: first,
                      last: last
                  };
              }
          );
          
    • require()
      • 모듈사용
      • 예제
        • //--------------------------------------------- 
          // main.js
          require([
                  'js/test.js'
              ], function(test) {
                  test.first(); // 'first'
                  test.last();  // 'last'
              }
          );
          


RequiredJS

  • RequireJS implements the AMD API
  • 지원하는 프레임웍
    • Dojo (1.7), MooTools (2.0), Firebug (1.8), jQuery (1.7).
  • Requried JS
    • define과 require의 차이점은?
      • define 은 모듈을 등록하여 export 할 경우 사용
      • require 는 기존 모듈을 사용하여 비지니스 로직을 구성할 경우 사용
        • require 함수에서는 새로운 모듈구현을 return 할수 없다.
      • http://stackoverflow.com/questions/9507606/when-to-use-require-and-when-to-use-define
    • define에서 기술된 모듈이 순서가 중요한 경우(의존성 관계)
      • define 에 기술된 모듈은 asynchronous 하게 병렬적으로 로딩되는데 AMD 를 지원한다면 자체적으로 관련 모듈에 대한 dependecy 에 대한 모듈이 로딩되고 factroy 함수가 실행된다.
      • define 에 기술된 모듈이 AMD 를 지원하지 않고 순서를 갖는 경우, 가령 define dependency 에 jquery ui, jquery 가 순서가 다르게 되있어 로딩순서가 중요한 경우 shim 설정으로 모듈간의 디펜던시를 기술

References

  • GitHub AMD Document
    • https://github.com/amdjs/amdjs-api/blob/master/AMD.md
  • JavaScript 표준을 위한 움직임 CommonJS와 AMD
    • http://helloworld.naver.com/helloworld/textyle/12864
  • RequireJS - AMD의 이해와 개발
    • http://helloworld.naver.com/helloworld/591319
  • Writing Modular JavaScript With AMD, CommonJS & ES Harmony
    • http://addyosmani.com/writing-modular-js/
  • Stackoverflow: Relation between CommonJS, AMD and RequireJS?
    • http://stackoverflow.com/questions/16521471/relation-between-commonjs-amd-and-requirejs
  • AMD: The Definitive Source
    • http://www.sitepen.com/blog/2012/06/25/amd-the-definitive-source/


Posted by leechwin