[JS] 48장 모듈

JH Cho·2022년 12월 26일
0

모던JS DeepDive 공부

목록 보기
23/27
post-thumbnail

JS DEEPDIVE 공부정리용 글입니다.

48.1_ 모듈의 일반적 의미

  • 모듈이란 애플리케이션을 구성하는 개별적 요소로 재사용 가능한 코드 조각을 의미.
  • 모듈은 기능을 기준으로 파일 단위로 분리
  • 모듈이 성립하기 위해선 자신만의 파일 스코프(모듈 스코프)를 가져야 한다.
    • 독자적 파일 스코프를 가진 모듈의 모든 자산(모듈에 포함된 변수, 함수, 객체)은 기본적으로 비공개 상태

    • 즉 모듈의 모든 자산은 캡슐화되어 다른 모듈에서 접근이 불가능하여 개별적 존재로 애플리케이션과 분리되어 존재함.


import / export

  • export : 공개가 필요한 자산에 한정하여 명시적 선택 공개
  • import : 모듈의 사용자는 모듈이 export한 자산 중 일부 또는 전체를 선택하여 자신의 스코프 내로 불러 재사용 가능

모듈의 장점

  • 개별적 파일로 분리되어 작성되기 때문에 코드의 단위를 명확히 분리하여 애플리케이션을 구성 가능
  • 재사용성이 좋아 개발 효율성유지보수성을 향상

48.2_ 자바스크립트와 모듈

  • 자바스크립트는 원래 모듈의 필수 기능인 import/export를 지원하지 않았음.
  • JS는 script 태그를 이용해서 외부의 JS 파일을 로드 가능하지만 파일마다 독립적 파일 스코프를 갖지 않는다.
  • 즉, 여러 개의 JS파일이 각자 script에 의해 로드되고 하나처럼 동작함.(하나의 전역 공유)

CommonJS, AMD

JS를 브라우저 환경에 국한하지 않고 범용적 사용을 위해 모듈 시스템이 필수가 되었고 그 결과 CommonJS와 AMD(Asynchronous Module Definition)이 제안됨.

  • JS 모듈 환경은 크게 위 둘로 나뉘며 JS 런타임 환경인 Node.js는 모듈 시스템의 사실상 표준인 CommonJS를 채택함.
  • 현재의 Node.js는 CommonJS와 거의 동일한 사양을 따른다.
  • 결과! -> Node.js 환겨에서는 파일별로 독립적 파일 스코프(모듈 스코프)를 갖는다.

48.3_ ES6 모듈

  • ES6에서는 클라이언트 사이드 JS에서도 동작하는 모듈기능을 추가했음.(IE제외 모든 브라우저에서 동작)

ES6 모듈 사용법

  • script 태그에 type="module" 어트리뷰트 추가
  • 확장자 mjs
<script type="module" src="app.mjs"></script>

48.3.1_ 모듈 스코프

  • ESM은 독자적인 모듈 스코프를 가짐.

ESM이 아닌 일반적 JS는 독자적 X
예) 모듈 두개 만들고~ 스크립트 태그에 달아보자.
다른 모듈에서 각자 선언한 변수는 window(전역)변수로 선언되어 값이 덮어 씌워진다.

  • ESM은 파일 자체의 독자적 모듈 스코프를 제공
  • ESM에서는 var로 선언해도 전역 변수로 등록되지 않음.
  • 모듈 내에서 선언한 식별자는 모듈 외부에서 참조 불가!!
  • 모듈 스코프가 다르기 때문!

48.3.2_ export 키워드

모듈은 독자적 모듈 스코프를 가지기에 모듈 내부에서 선언한 식별자를 해당 모듈 내부에서만 참조 가능하다.
그러므로 모듈 내부의 식별자를 외부에서 사용하기 위해선 export 키워드를 사용한다.
(변수, 함수, 클래스 등 모든 식별자 export 가능)

// lib.mjs
// 변수의 공개
export const pi = Math.PI;

// 함수의 공개
export function square(x) {
  return x * x;
}

// 클래스의 공개
export class Person {
  constructor(name) {
    this.name = name;
  }
}
  • 한꺼번에 객체형태로 export하는 방법도 있다!
export { pi, square, Person };

48.3.3_ import 키워드

  • 다른 모듈의 export 식별자를 자신의 모듈 스코프 내부로 로드하기 위한 import 키워드
  • 다른 모듈이 export한 식별자 이름으로 import해야하며 ESM의 경우 파일 확장자를 생략할 수 없다.
// app.mjs
// 같은 폴더 내의 lib.mjs 모듈이 export한 식별자 이름으로 import한다.
// ESM의 경우 파일 확장자를 생략할 수 없다.
import { pi, square, Person } from './lib.mjs';

console.log(pi);         // 3.141592653589793
console.log(square(10)); // 100
console.log(new Person('Lee')); // Person { name: 'Lee' }

// 
<!DOCTYPE html>
<html>
<body>
  <script type="module" src="app.mjs"></script>
</body>
</html>
  • app.mjs는 애플리케이션의 진입점으로 반드시 script 태그로 로드해야 한다.
  • lib.mjs는 app.mjs의 import 문에 의해 로드되는 의존성(dependency)
  • 따라서 lib.mjs는 script태그로 로드하지 않아도 됨.

모든 export 식별자를 한 번에 import하기

// app.mjs
// lib.mjs 모듈이 export한 모든 식별자를 lib 객체의 프로퍼티로 모아 import한다.
import * as lib from './lib.mjs';

console.log(lib.pi);         // 3.141592653589793
console.log(lib.square(10)); // 100
console.log(new lib.Person('Lee')); // Person { name: 'Lee' }

각 식별자 이름을 변경도 가능.

// app.mjs
// lib.mjs 모듈이 export한 식별자 이름을 변경하여 import한다.
import { pi as PI, square as sq, Person as P } from './lib.mjs';

console.log(PI);    // 3.141592653589793
console.log(sq(2)); // 4
console.log(new P('Kim')); // Person { name: 'Kim' }

export default 키워드

  • 이 경우는 var, let, const 키워드 사용불가
// lib.mjs
export default x => x * x;

// lib.mjs
export default const foo = () => {};
// => SyntaxError: Unexpected token 'const'
// export default () => {};

// app.mjs
import square from './lib.mjs';

console.log(square(3)); // 9
profile
주먹구구식은 버리고 Why & How를 고민하며 프로그래밍 하는 개발자가 되자!

0개의 댓글