(10장) 모듈 [자바스크립트 완벽 가이드 7판]

iberis2·2023년 2월 13일
0

모듈

모듈이란 ?
전체를 이루는 부품 하나하나를 말하며, 자바스크립트 파일 하나로 볼 수 있다.
모듈화를 통해 복잡하고 많은 양의 코드를 기능에 따라 각각의 파일로 나눠 관리할 수 있다.

모듈화(Modularization)의 장점

  • 코드를 효율적으로 관리할 수 있다.
    • 세부 사항을 숨기고, 다양한 소스에서 가져 온 코드가 서로 충돌할 걱정 없이 큰 프로그램에 모을 수 있다.
  • 비슷한 기능이 필요할 때 다른 프로그램에서 재사용할 수 있다.

🖥 ES6 이후 모듈 문법

🗃 모듈 스코프(module scope)

일반적인 스크립트에서는 최상위에서 선언한 변수, 함수, 클래스는 모두 모든 스크립트가 공유하는 전역 컨텍스트에 들어간다.

반면에 모듈 파일 내부에서 선언한 변수나 함수는 (명시적으로 내보내지 않는 한) 해당 모듈 안에서만 사용이 가능하다.
즉, 모듈 파일이 가져야 하는 독립적인 스코프를 모듈 스코프라고 한다.

🗃 일반 script 파일과 다른 특징

<!--index.html 파일-->

<script src="index.js" type="module"></script>

📍 HTML파일에서 자바스크립트 파일을 불러올 때 모듈 스코프를 갖게 하려면 < script >태그에 type속성을 module이라는 값으로 지정해 주어야 한다.

📍 브라우저에서 local 컴퓨터에 있는 html 파일을 불러올 때에는 자바스크립트의 모듈 문법은 사용할 수 없다.
→ 따라서 서버를 통해 html 파일을 실행해야 한다.

  • vs Code의 Live Server extension을 활용할 수도 있다.

📍 'use strict'를 쓰지 않아도 자동으로 스트릭트 모드에 들어간다.

  • with문, arguments 객체, 선언되지 않은 변수를 사용할 수 없다.
  • (최상위 코드에서도) this는 undefined이다.

🗃 export와 import

// printer.js
export const title = 'MyPrinter';

export function print(value) {
  console.log(value);
};

모듈 스코프를 가진 파일에서 외부로 내보내고자 하는 상수, 변수, 함수, 클래스의 선언 앞에 export 키워드를 추가해서 내보낸다.

  • export는 이름 있는 선언에서만 사용할 수 있다.
    • export default 는 익명 함수/클래스 표현식에서도 사용할 수 있다.
  • export 와 import는 자바스크립트 코드 최상위 레벨에만 존재할 수 있다.
    • 클래스, 함수, 루프, 조건문 안에서 사용할 수 없다.

📍 { 중괄호 }

/* 한꺼번에 export 하기 */

const title = 'MyPrinter';

function print(value) {
  console.log(value);
}

function printArr(arr) {
  arr.forEach((el, i) => {
    console.log(`${i + 1}. ${el}`);
  });
}

export { title as printerTitle, print, printArr };

선언된 변수나 함수를 중괄호로 모아 한꺼번에 내보낼 수도 있다.
이때 as 키워드를 활용하면 이름을 변경해서 export할 수도 있다.

// index.js
import { title, print } from './printer.js';

print(title);

모듈 파일에서 내보낸 변수 등은 다른 파일에서 import 키워드를 통해 가져온다.

  • export 에서 내보낸 이름으로 가져올 수 있다.
  • 모듈 이름은 작은따옴표큰따옴표 안에 불변하는 문자열로 표기해야한다.
    • 값이 문자열인 변수, 표현식, `` 백틱 은 사용할 수 없다.
  • export default로 익명 함수/클래스 표현식을 내보내는 경우 import로 가져오는 모듈에서 이름을 지정한다.

📍 as 키워드

/* 이름 바꿔 import 하기 */
import { title as printerTitle, print, printArr } from './printer.js';
import { title, data as members } from './members.js';

printer(title);
arrPrinter(members);

import 키워드를 통해 모듈을 불러올 때 as 키워드를 활용하면 import하는 대상들의 이름을 변경할 수 있다.

  • 불러오는 대상들의 이름이 중복되는 문제를 해결할 수도 있다.

📍 * 키워드

/* 한꺼번에 import 하기 */
import * as printerJS from './printer.js';

console.log(printerJS.title); // MyPrinter
console.log(printerJS.print); // ƒ print(value) { console.log(value); }

import할 때 와일드카드 문자(*)와 as를 활용하면 모듈 파일에서 export하는 모든 대상을 하나의 객체로 불러올 수 있다.

📍 export default 키워드

const title = 'MyPrinter';

function print(value) {
  console.log(value);
}

export default print;

함수나 클래스 하나만 내보내는 모듈은 보통 export default를 사용한다.

  • exportexport defult를 섞어 쓸 수는 있지만, export default 를 여러개 쓸 수는 없다.

기명 뿐만 아니라 익명 함수/클래스 표현식에도 쓸 수 있다.

  • import 하는 모듈에서 이름을 지정한다.
/* export default 불러오기 */
import { default as printerJS } from './printer.js';

console.log(printerJS.title); // MyPrinter
console.log(printerJS.print); // ƒ print(value) { console.log(value); }

default export는 기본적으로 위와 같이 import하여 불러올 수 있고,

/* 축약형으로 불러오기 */
import printerJS from './printer.js';

console.log(printerJS.title); // MyPrinter
console.log(printerJS.print); // ƒ print(value) { console.log(value); }

위와 같이 축약형 문법으로 import 할 수도 있다.

🖥 노드 모듈

노드에서 각 파일은 비공개 네임스페이스를 가진 독립적인 모듈입니다.
(...중략...)

  • 노드 모듈은 require() 함수를 통해 다른 모듈을 가져오고,
  • Exports 객체의 프로퍼티를 수정하거나,
  • module.exports 객체 자체를 바꾸는 방법으로 공개 API를 내보냅니다.
    〖자바스크립트 완벽 가이드〗 -291p

🗃 전역 객체 exports

function add(a, b){
   return a + b;
 }

let name = 'Janny';

exports.name = name;
exports.plus = add; 
// 프로퍼티 네임을 'plus'로 지정했으므로, 
// 다른 모듈에서 사용하려면 add가 아닌 plus로 로드해야 사용할 수 있다.

노드 자바스크립트 모듈을 내보내기 위해서는 전역객체 exports의 프로퍼티로 할당하면 된다.

  • 프로퍼티 네임을 원하는대로 지정해서 내보낼 수 있다.

🗃 module.exports

let calculator = {
  PI: 3.14,
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
  multiply: (a, b) => a * b,
  divide: (a, b) => a / b,
}

module.exports = calculator;

module.exports의 기본값은 exports가 참조하는 것과 같은 객체이다.
공개하고 싶은 것들을 모은 객체를 외부에 공개할 때 사용할 수 있다.

🗃 require()

const fs = require('fs');
const http = require('http');

노드 안에 내장된 시스템 모듈이나 패키지로 설치한 모듈은 모듈 이름만 사용한다.

  • / (파일 시스템 경로)를 사용하지 않는다.
// 같은 디렉토리 안에 있는 상대 경로에서 모듈을 가져 옴
const { plus } = require('./math-tools.js'); 
const calculator = require('./calculator.js');

let result = plus(1, 2);
console.log(result); // 3

result = calculator.add(1, 2);
console.log(result); // 3

require 함수는 모듈을 로드해서 객체 하나를 리턴한다.
구조 분해 할당을 통해 원하는 프로퍼티만 가져올 수도 있다.

직접 만든 모듈을 가져올 때는 require 함수의 인자로 상대경로를 써야한다.

  • js 확장자를 생략할 수 있지만 명시적으로 쓰는 경우가 더 많다.

자바스크립트 모듈의 역사

  • 자바스크립트 초기에는 즉시 호출하는 함수 표현식을 활용
  • 노드 자바스크립트 언어를 바탕으로 JS만의 모듈 시스템을 만듦
    • 노드 모듈은 require()를 통해 가져오며, 내보낼 값은 Exports객체의 프로퍼티나 module.exports 프로퍼티로 정의한다.
  • ES6 이후 importexport 키워드를 사용
    • ES2020에서 import()를 사용한 동적 가져오기 지원 추가
profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글