Muscardinus

Modules in JS 본문

FrontEnd/JavaScript Basics

Modules in JS

Muscardinus 2020. 12. 14. 17:22
728x90

What is Modules ?

모듈은 단지 한 개의 파일에 불과하다. 개별의 파일 안에는 개별적인 로직이 있으며, 일반적으로 모듈은 대개 클래스 혹은 특정한 목적을 가진 복수의 함수로 구성된 라이브러리 하나로 구성된다.

 

Module Patterns

Block Scope이 나오기 전에 JS에는 Global Scope과 Function Scope이 존재하였고, Module Pattern이라는 개념을 도입하기 위해서 JS에서는 Function Scope 위에 Module Scope을 도입하였다. 이를 통하여 우리는 Globla Scope에 선언하지 않고도, 함수들 끼리 변수들을 공유할 수 있었다. 함수로 된 모듈은 단지 IIFE(Immediately Invoked Function Expression) 형태였다. 추후 다른 글에서 IIFE에 대해서 연재할 예정이다.

 

var globalScopeVar = "I can be accessed anywhere";
var moduleName = (function (globalScopeVar) {
  // add private variables here
  var privateVar = "I cannot be accessed outside";
  // create the function
  function say(msg1, msg2) {
    var say1 = Math.floor(Math.random() * msg1.length);
    var say2 = Math.floor(Math.random() * msg2.length);
    return say1 > say2 ? say1 : say2;
  }
})(globalScopeVar);

 

초기 Modules에 관한 Issue

초기 모듈에는 몇 가지의 문제가 있었다.

  • Naming Conflict - const를 사용하지 않고 모듈을 선언하면 모듈 이름의 중복이 발생할 확률이 있다.
  • Dependency Issues - html 파일 상에서 script의 순서가 잘못 될 경우, 예를 들면 jQuery를 필요로 하는 JS 파일이 jQuery 보다 먼저 선언되면 오류가 발생한다.

이러한 문제를 해결하기 위해, ES6가 나오기 전까지 2가지 방법으로 해결하려고 노력하였다.

 

1. CommonJS

require과 exports를 사용하여 module를 활용한다. require은 다른 모듈에서 import 하기 위해서 사용하는 함수이며, exports는 함수들이 export되는 객체이다. CommonJS는 동기적(Synchronous)하게 작동하기 때문에, 만약에 하나의 모듈이 매우 무거울 경우, 이전 모듈이 import 되기 전 까지 다음 모듈은 기다려줘야한다. 이것은 browser들에게 이상적인 상황이 아니다. 하지만, NodeJS를 사용하는 사람이라면, require에 매우 익숙할 것 이다.

 

2. AMD (Asynchronous Module Definition)

이름과 같이 AMD는 module을 비동기적으로 load 한다. 

define(["module1", "module2"], function (module1, module2) {
  console.log(module1.setName());
});

 

위와 같이 define 함수는 첫번째 인자로 배열을 받고, 그 배열 안에는 필요한 모듈들을 넣는다. 모듈들이 load 완료 되면, 이제 callback 함수가 실행된다.

 

 

ES6 Modules

ES6가 등장하면서 위 두가지 해결책은 거의 안 쓰이게 되었다. 이제 우리는 import와 export를 사용하여 모듈을 실행한다. 아마 React를 사용하고 있는 개발자라면 매우 친숙하게 느껴질 것 이다.

 

const globalScopeVar = "I can be accessed anywhere";

export function name(msg1, msg2) {
  const say1 = Math.floor(Math.random() * msg1.length);
  const say2 = Math.floor(Math.random() * msg2.length);
  return say1 > say2 ? say1 : say2;
}

 

위에 있는 Module Pattern의 코드를 ES6 형식으로 바꾸면 위와 같은 코드가 된다. 훨씬 보기 편하다

 

Export 하는 방식에는 두 가지가 있다.

Named와 Default 방식

import { importFnName } from "./script.js";
// with a default function the {} are not needed
import name from "./script.js";
// both default and named function import
import name, { importFnName } from "./script.js";
export default function name(msg1, msg2) {
const say1 = Math.floor(Math.random() * msg1.length);
const say2 = Math.floor(Math.random() * msg2.length);
return say1 > say2 ? say1 : say2;
}

Default로 선언된 함수는 {} 없이 import 해 올 수 있다.

728x90

'FrontEnd > JavaScript Basics' 카테고리의 다른 글

JS Types  (0) 2020.12.15
Error Handling  (0) 2020.12.14
Call Stack And Memory Heap  (0) 2020.11.30
Writing Optimized Code  (0) 2020.11.30
What is JavaScript Engine?  (1) 2020.11.30
Comments