티스토리 뷰

13.1 Modules, instroduction

export 지시자는 변수나 함수 앞에 붙이면 다른 외부 모듈에서 접근할 수 있다.

import 지시자를 사용하면 외부 모듈의 기능을 가져온다.

// 📁 sayHi.js
export function sayHi(user) {
  alert(`Hello, ${user}!`);
}

// -------------

// 📁 main.js
import {sayHi} from './sayHi.js';

alert(sayHi); // 함수
sayHi('John'); // Hello, John!

<script type="module"> 같은 속성을 설정해 해당 스크립트가 모듈임을 브라우저가 알 수 있도록 해야 한다.

Core module features

  • 모듈은 항상 엄격모드로 실행된다.
  • 모듈은 자신만의 스코프가 존재, 모듈 내부에서 정의된 함수, 변수는 다른 스크립트에서 접근 안됨
  • 한 번만 평가된다. 동일한 모듈이 여러 곳에서 사용되어도 최초 호출 시 한 번만 실행된다.
// 📁 admin.js
export let admin = {
  name: "John"
};

// -----------

// 📁 1.js
import {admin} from './admin.js';
admin.name = "Pete";

// 📁 2.js
import {admin} from './admin.js';
alert(admin.name); // Pete

// 1.js와 2.js 모두 같은 객체를 가져오므로
// 1.js에서 객체에 가한 조작을 2.js에서도 확인할 수 있습니다.

위 예시에서 1.js에서 수정한 admin 객체를 2.js에서도 확인할 수 있다. 

import.meta

import.meta 객체는 현재 모듈에 대한 정보를 제공한다. 환경마다 제공되는 정보는 조금씩 다르다. 한 번씩 확인해 보면 좋겠다.

Browser-specific features (해당 내용은 브라우저 환경에서 사용할 때 유효함. 추후 다시 살펴볼 것)

13.2 Export and Import

Export before declarations

내보내기는 아래 예시처럼 가능하다.

// 배열 내보내기
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 apart from declarations

// 📁 say.js
function sayHi(user) {
  alert(`Hello, ${user}!`);
}

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

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

import *

// 📁 main.js
import {sayHi, sayBye} from './say.js';

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

// ----------------

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

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

위 예시처럼 한꺼번에 모든 걸 가져오는 방식은 코드가 짧아져서 좋지만, 웬만하면 구체적으로 명시하는 것이 좋다. 

  • 웹팩과 같은 빌드 툴이 번들링 및 최적화 수행하는 과정에서 리소스가 삭제되기도 한다.
  • 어떤 것을 가져올지 명시하면 이름이 간결해진다.
  • 어디서 어떻게 쓰이는지 명확하여 리팩토링, 유지보수에 유리하다.

import 'as'

as를 사용해서 이름을 바꿔서 가져오기가 가능하다.

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

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

export 'as'

export도 마찬가지로 as를 사용할 수 있다.

// 📁 say.js
...
export {sayHi as hi, sayBye as bye};

// --------------

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

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

export default

모듈 내부에는 여러 함수가 존재할 수도 있고, 하나의 클래스만 존재하는 등 여러 가지 형태의 모듈이 존재할 수 있다. export default는 해당 모듈엔 개체가 하나만 있다는 의미로 사용하는 문법이다. 아래 예시를 보면 export default를 사용한 모듈은 중괄호 없이 가져올 수 있다.

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

// ------------------

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

new User('John');

default export는 파일당 최대 하나만 있을 수 있으므로 내보낼 개체에 이름이 없어도 상관이 없다. 

export default class { // 클래스 이름이 없음
  constructor() { ... }
}

// ------------------

export default function(user) { // 함수 이름이 없음
  alert(`Hello, ${user}!`);
}

// ------------------

// 이름 없이 배열 형태의 값을 내보냄
export default ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

만약 이름이 없는데, default를 붙이지 않았다면 에러가 발생한다.

'default' name

아래와 같이 따로 작성해 줄 수도 있다.

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

// 함수 선언부 앞에 'export default'를 붙여준 것과 동일합니다.
export {sayHi as default};

아래는 default export와 다수의 named export가 있는 경우 함께 import 하는 예시이다.

// 📁 user.js
export default class User {
  constructor(name) {
    this.name = name;
  }
}

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

// ------------

// 📁 main.js
import {default as User, sayHi} from './user.js';

new User('John');

 

Re-export

export... from... 구문을 사용해서 가져온 모듈을 다시 내보내기 할 수도 있다. 

export {sayHi} from './say.js'; // sayHi를 다시 내보내기 함

export {default as User} from './user.js'; // default export를 다시 내보내기 함

13.3 Dynamic imports

The import() expression

import() 표현식은 모듈이 내보내는 모든 것들을 포함하는 객체를 담은 이행된 프라미스를 반환한다. 어디서든 호출 가능하다. 

let modulePath = prompt("어떤 모듈을 불러오고 싶으세요?");

import(modulePath)
  .then(obj => <모듈 객체>)
  .catch(err => <로딩 에러, e.g. 해당하는 모듈이 없는 경우>)
// 📁 say.js
export function hi() {
  alert(`안녕하세요.`);
}

export function bye() {
  alert(`안녕히 가세요.`);
}

// --------------

let {hi, bye} = await import('./say.js');

hi();
bye();

default export는 아래와 같이 사용하면 된다.

// 📁 say.js
export default function() {
  alert("export default한 모듈을 불러왔습니다!");
}

// -----------------
let obj = await import('./say.js');
let say = obj.default;
// 위 두 줄을 let {default: say} = await import('./say.js'); 같이 한 줄로 줄일 수 있습니다.

say();

 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday