Module 이란

  • 재사용이 가능한 코드를 분리하여 다른 파일에서도 사용할 수 있도록 만들어둔 단위라고 생각하면 편할 것 같다.
  • 자바스크립트에서는 모듈기능이 없었지만 전역 스코프에 대한 단점을 보안하기위해서 ES6부터 추가되었다.
  • 모듈은 작성한 파일에서 export 해주고 main.js 같은 최상위 파일 또는 모듈을 사용하고자하는 파일에서 import 해줌으로 모듈화된 파일을 사용해준다.
  • 모듈화를 해줌으로써 전역 스코프를 피하고 모듈안에 한정된 모듈 스코프를 적용해줄 수 있게된다.
  • 모듈을 HTML 페이지에 적용 시에는 <script> 요소에 type='module'을 넣어줘야 한다.

Module의 탄생

1. 자바스크립트의 스코프

  • 자바스크립트는 각기 다른 파일을 HTML에 로드해줘도 결국에는 하나의 전역스코프를 공유한다. 전역스코프를 공유한다는 것은 전역으로 선언한 변수의 이름이 겹친다면 해당 변수는 재할당 될 수 있으며, 이로인해서 오류를 발생시킬 수 있다는 말이다.

  • 예시

    // app.js
    var title = "Summer's Bolg"
    
    // sidebar.js
    var title = 'Discription'
    
    <!DOCTYPE html>
    <html>
    <body>
      <script src="app.js"></script>
      <script src="sidebar.js"></script>
    </body>
    </html>
    
    • 위와 같이 파일을 나눠서 작성했지만 자바스크립트가 하나의 전역 스코프를 공유하면서 title이 sidebar.js에서 재할당 되었으며 의도한 title과는 다른 내용이 출력된다. image

2. IIFE

  • 전역변수의 문제점을 해결하는 방법으로도 나왔던 즉시실행 함수이다. 즉시 실행 함수
  • var 키워드를 통해서 변수를 선언하게되면 전역변수로 선언되어 하나의 전역스코프를 공유하는 자바스크립트에서는 오류가 생길 수 있었다. 여기서 var 키워드는 함수 레벨 스코프로 함수의 중괄호({ }) 안에서는 지역 변수의 역할을 하게 됨을 이용한 방법이다.
  • 하지만 즉시 실행 함수는 함수를 즉시 실행하며 스코프만 적용해줄 뿐 실질적인 해결책을 줄 수는 없다.

3. Library

  • 모듈 기능이 없는 자바스크립트에서는 모듈화를 위한 라이브러리가 있다.
  • 대표적으로 CommonJS 와 AMD가 있으며 Node.js 에서는 CommonJS를 따라서 모듈을 지원한다.

4. ES6 모듈

  • ES6부터 모듈 기능을 추가되어 라이브러리의 도움 없이도 모듈 기능을 사용할 수 있게되었다.
  • html 파일에 자바스크립트 파일을 불러오는 script 태그에 타입을 모듈로 지정해준다.
  • 불러오는 자바스크립트의 타입은 반드시 module로 해줘야 하며 파일 확장자는 mjs로 모듈임을 명시해주는 것이 좋다.
    <script type='module' src='sidebar.mjs'></script>
    
  • ES6 모듈 지원 현황(22.04.22)
    • Safari 10.1.
    • Chrome 61.
    • Firefox 60.
    • Edge 16.

Module 사용

scope

  • 모듈로서 작성한 자바스크립트는 모듈 파일 자체 스코를 갖게 되며 모듈 스코프라고 한다.
  • 모듈 파일에서는 var 키워드로 변수를 선언해도 전역 스코프를 갖지 않게 된다.

export

  • 모듈 내에서 선언한 함수, 변수등을 다른 파일(또는 모듈)에서 사용하기위해서는 해당 모듈을 export해줘야 한다.
    • 각각 export 하기
      export const name = 'summer';
      
      export function sum(num) {
        return num + num;
      }
      
      export class Person {
        constructor(name) {
          this.name = name;
        }
      }
      
    • 한번에 export 하기
      const name = 'summer';
      
      function sum(num) {
        return num + num;
      }
      
      class Person {
        constructor(name) {
          this.name = name;
        }
      }
      
      export { name, sum, Person };
      

import

  • 모듈을 export 해줬다면 이제는 import를 통해 다른 파일에서도 사용할 수 있다.
    • 각각 import 하기
      // sidebar.mjs
      import { name, sum, Person } from './example.mjs';  // 파일 확장자는 생략가능
      
      console.log(name);
      console.log(sum(3));
      console.log(new Person('winter'));
      
    • 전체 import 하기
      // sidebar.mjs
      import * as example from './example';
      
      console.log(name);
      console.log(sum(3));
      console.log(new Person('winter'));
      
    • import한 모듈 이름 변경하기
      // sidebar.mjs
      import { name as Name, sum as sumNumber, Person as PS } from './example';
      
      console.log(Name);
      console.log(sumNumber(3));
      console.log(new PS('winter'));
      
    • 실행 결과 image

export default

  • 하나만 내보낼때는 export default 를 써준다.
  • export default 사용 시 var, let, const 키워드는 사용할 수 없다.
  • export default 로 내보낸 모듈은 import 할 때 중괄호 ({ })를 사용하지 않는다.
    • export
      export default function sum(num) {
        return num + num;
      }
      
    • import
      // sidebar.mjs
      import sum from './example';  // 중괄호 { } 를 사용하지 않고 import 해준다.
      
      console.log(sum(5));  // 10 출력