모듈

MyeonghoonNam·2021년 8월 3일
0
post-custom-banner

모듈

  • 웹 사이트가 하는 일이 증가함에 따라 스크립트 파일의 양이 증가하게되었고 예전에는 전역 스코프를 활용하여 스크립트 파일들의 통신을 담당하였지만 스크립트 파일간의 실행순서와 의존도 문제가 심해짐에 따라 모듈이 만들어졌다.

  • 모듈은 스크립트 파일간의 의존성을 쉽게 파악하며 훨씬 간편학 관리할 수 있고 실행순서를 쉽게 제어할 수 있다.

  • 모듈과 컴포넌트는 자주 혼용되며 모듈설계 시점에 의미있는 요소를 가리키며, 컴포넌트런타임 시점에 의미있는 요소를 가리킨다.

  • 즉, 모듈은 우리가 의식적으로 나눈 요소이고, 컴포넌트나눈 요소에 포함되어 실행되어지는 요소를 말합니다.

  • 모듈은 로컬 파일에서 동작하지 않고 HTTP 또는 HTTPS 프로토콜을 통해서만 동작한다.


기초 문법

export

변수나 함수, 클래스를 선언할 때 맨 앞에 export를 붙이면 내보내기가 가능합니다.

// 배열 내보내기
export let months = ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

// 상수 내보내기
export const MODULES_BECAME_STANDARD_YEAR = 2015;

// 클래스 내보내기
export class User {
  constructor(name) {
    this.name = name;
  }
}

선언부와 export가 떨어져 있어도 내보내기가 가능합니다.

function sayHi(user) {
  alert(`Hello, ${user}!`);
}

function sayBye(user) {
  alert(`Bye, ${user}!`);
}

export {sayHi, sayBye}; // 두 함수를 내보냄

export 'as'

sayHi와 sayBye를 각각 hi와 bye로 이름을 바꿔 내보내 봅시다.

export {sayHi as hi, sayBye as bye};
// 이제 다른 모듈에서 이 함수들을 가져올 때 이름은 hi와 bye가 됩니다.

import * as say from './파일명.js';

say.hi('John'); // Hello, John!
say.bye('John'); // Bye, John!

export default

모듈은 export default라는 특별한 문법을 지원합니다. export default를 사용하면 해당 모듈엔 개체가 하나만 있다는 사실을 명확히 나태낼 수 있습니다.

export default class User { // export 옆에 'default'를 추가해보았습니다.
  constructor(name) {
    this.name = name;
  }
}

파일 하나엔 대개 export default가 하나만 있습니다.

이렇게 default를 붙여서 모듈을 내보내면 중괄호 {} 없이 모듈을 가져올 수 있습니다.

import User from './user.js'; // {User}가 아닌 User로 클래스를 가져왔습니다.

new User('John');

import

가져오고 싶은 함수를 아래와 같이 이에 대한 목록을 만들어 import {...}안에 적어주면 됩니다.

import {sayHi, sayBye} from './파일명.js';

sayHi('John'); // Hello, John!
sayBye('John'); // Bye, John!

가져올 것이 많으면 import * as <obj> 처럼 객체 형태로 원하는 것들을 가지고 올 수 있습니다.

import * as say from './say.js';

say.sayHi('John');
say.sayBye('John');

이렇게 한꺼번에 모든 걸 가져오는 방식을 사용하면 코드가 짧아집니다. 그런데도 어떤 걸 가져올 땐 그 대상을 구체적으로 명시하는 게 좋습니다.


import ‘as’

as를 사용하면 이름을 바꿔서 모듈을 가져올 수 있습니다.

import {sayHi as hi, sayBye as bye} from './say.js';

hi('John'); // Hello, John!
bye('John'); // Bye, John!


구현

// hello.js
export function hello(name) {
  console.log(name);
}
// index.html
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Module Test</title>
  </head>
  <body>
    <script type="module">
      import { hello } from './test.js';

      hello('Nam');
    </script>
  </body>
</html>
  • 결과

특징

  • 항상 use strict(엄격 모드)로 실행된다.
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Module Test</title>
  </head>
  <body>
    <script type="module">
      let a = 5;
      let b = 10;

      c = a + b; // 엄격 모드이므로 선언안된 c 오류

      console.log(c);
    </script>
  </body>
</html>

  • 모듈 레벨의 스코프가 존재한다.
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Module Test</title>
  </head>
  <body>
    <script type="module">
      let a = 5;
      let b = 10;

      const c = a + b;
    </script>

    <script type="module">
      console.log(c); // module 스크립트는 일단 스크립트와 달리 import 하지 않는한 전역스코프에 등록되지 않으므로 참조불가
    </script>
  </body>
</html>

  • 단 한 번만 평가된다.
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Module Test</title>
  </head>
  <body>
    <script type="module">
      import './hello.js';
    </script>

    <script type="module">
      import './hello.js'; // 두 번 호출되었지만 실행은 단 한 번만 한다.
    </script>
  </body>
</html>

  • 지연실행이 이루어진다.
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Module Test</title>
  </head>
  <body>
    <script>
      // DOM이 생성되기 전에 실행된다.
      console.log('text1');
    </script>

    <script type="module">
      // DOM이 만들어진 후 실행된다.
      // defer 옵션을 적용한 효과와 동일
      console.log('text2');
    </script>
  </body>
</html>

profile
꾸준히 성장하는 개발자를 목표로 합니다.
post-custom-banner

0개의 댓글