본문 바로가기

JavaScript

JavaScript - 모듈화

소스코드가 길어질 경우, 하나의 파일로 관리하는 것이 아니라 여러개의 파일로 분리해서 관리하는 것이 좋다.

공통된 기능이나 특별한 목적에 따라 각각의 파일로 분리하는 과정을 '모듈화'라고 하고, 각각의 파일을 '모듈'이라고 한다.

 

모듈화를 하면 코드를 효율적으로 관리할 수 있고, 다른 프로그램에서 재사용할 수 있다는 장점이 있다.

ES5이전까진 모듈화를 할 수 있는 기능이 없었다.

모듈파일의 조건

  • 모듈파일이 가지는 독립적인 스코프 = 모듈스코프.
  • 모듈에서 사용하는 변수나 함수는 해당 모듈에서만 사용할 수 있어야한다는 것이다.

무슨 뜻이냐면,

한 html파일에서 2개의 자바스크립트 파일을 가져오고있다고 하자.

index.html에서 print.js와 draw.js 둘을 불러오고 있다.

그럼 print.js에서 선언된 변수를 draw.js에서 사용할 수 있는데, 마치 한 파일에 작성된 것과 같다.

이러한 현상은 큰 문제가 될 수 있다.

함수나 변수명이 중복된경우 덮어씌워지며 의도치않은 문제가 발생할 수도 있고 그 외의 다른 syntaxError가 발생할 수도 있기 때문이다.

자바스크립트에서 모듈스코프를 만들어주려면, html에서 자바스크립트 파일을 불러올 때 설정한다.

모듈파일 설정하기

// 기존
<script src=“print.js”></script>

// 모듈 스코프
<script type=“module” src=“print.js”></script>
  • 브라우저에서 내 컴퓨터의 html파일을 불러올 경우 자바스크립트의 모듈문법은 사용할 수 없다.(에러 발생)
  • 자바스크립트의 모듈 문법을 만들 때, 문법자체의 보안 요구사항으로인해 에러가 발생하도록 설계되어있기 때문이다.
  • 이 문제를 해결하려면 브라우저에서 파일을 직접 불러오는 것이 아니라, 서버를 통해 html파일을 실행해야한다.
  • 현재는 live server를 사용하면 되겠다.

모듈 문법

모듈스코프를 갖고있게 되면, 다른 모듈에서는 내부의 변수 함수 등을 사용할 수 없지만,

모듈문법을 통해서 사용할 수 있다.

예시는 다음과 같다.

// print.js의 변수와 함수를 draw.js에서 가져다 쓰고싶은 상황.
// print.js
export const title = ‘kong’;
export function print(value){
	console.log(value);
}

// draw.js
import { title, print } from ‘./print.js’;
print(title);

export키워드로 내보낼 변수와 함수를 지정한다.

가져다 쓸 곳에서는 Import로 해당 변수와 함수를 받아온 후 사용가능하다.

 

이렇게 서로서로 모듈을 export, import해서 가져다 쓸 수 있기 때문에,

html파일에서는 스크립트 파일을 여러개 불러올 필요가 없으며 하나만 가져오는 편이 좋다.

 

모듈 import할 때 이름 변경하기

// 원래 이름 as 바뀔이름
import { title as bigTitle } from ‘./print.js’;

모듈 전체 import 하기

import * as printJS from ‘./print.js’;

print.js에서 export하고있는 모든 것들을 객체로 가져온다.

(하지만 필요한 것만 가져오는 것이 가장 좋다.)

'*' 는 '와일드카드 문자'라고 부른다.

모듈전체 export하기

export { title, print } ;

위와같이 모듈파일의 맨 마지막에 export문을 넣음으로 어떤 값들을 export하는지 알아보기 쉽게 작성할 수 있다.

그리고 이렇게 export할 경우, 미리 이름을 바꿀 수도 있는데 아래와 같이 작성하면 된다.

export { title as bigTitle, print as consolePrint } ;

default export

export default title;
export default ‘aaa’;

이렇게 변수나 함수를 내보낼 수도 있고, 리터럴값 그대로를 내보낼 수도 있다.

default export는 모듈 1개당 딱 1번 사용할 수 있다.( 1개의 숫자, 1개의 객체, 1개의 배열 ...)

그리고 보내는 값도 딱 1개의 데이터만 보낼 수 있다.

그리고 default로 export한 값은, 다른 곳에서 import하는 방법도 약간 다르다.

import { default as print } from ‘./print.js’;

이렇게 default로 임포트하긴 하지만, 이대로 쓸 수는 없고 as를 통해 이름을 지정해줘야 한다.

 

export default title; // default export 라고 부른다.
export { title, print } ; // named export 라고 부른다.

 

default export축약

그리고 default export축약에는 특별한 문법이 있는데, 아래와같이 축약이 가능한 부분이다.

// 기존
import { default as title, print } from ‘./print.js’;

// 축약
import title, { print } from ‘./print.js’;

그래서 import문을 보면 해당 변수가 default로 export된것인지 아닌지 구분할 수 있다.

 

만약 와일드카드 문자로 전체를 import함 + default export된 것이라면

import * as printJS from ‘./print.js’;
console.log(printJS.default);

위와같이 default라는 이름으로 접근할 수 있다.

 

default export된 것과, named export된 것을 둘 다 import하려면 조금 구문이 지저분해진다.

따라서 일반적으로 export할 때에, export할 것이 여러개라면 named export를 사용하고,

export할 것이 한 개라면 default export를 사용한다.

둘 다 쓰지 않고 둘 중 하나만 골라서 쓰는 경우가 일반적이다.

 

그리고 default export는 딱 한 개의 값만 내보낼 수 있다고 했지만

export default { title, print };

위와같이 객체로 묶어서 여러개의 값을 보낼 수 있다.

({ title : title, print : print } 객체로 보내는 것이다.)

하지만 객체로 값을 보내게되면 이름을 수정할 수 없는 단점도 있으니 named export를 사용하는 것이 더 좋겠다.