💙 들어가며
ES6에서 ES5의 문제점을 보완한 것들에 대해서 배워보자!
✏️ 학습내용 정리
#ES6에서 크게 달라진 것14: ES6 Module
스크립트 파일을 class 단위로 나눠서 작성할 수 있게 되었다.
그럼 이렇게 나누어서 작성한 스크립트 파일을 어떻게 서로 연동시킬 수 있을까?
기존에는 스크립트가 다른 스크립트를 import하지 못했기 때문에
html에게 도움을 받았어야 했다.
파일들이 html의 도움을 받아서 script 파일을 써야 했기 때문에
html 상에서 script파일을 불러올 때 순서도 중요했고,
(html 문서에서 script들을 사용하는 순서에 따라서 쭉 작성하고
끝에 defer를 쓰는 방법으로 html문서를 순서대로 구동하고 난 뒤에
스크립트 파일을 구동하는 식으로 조작했다.)
이렇게 불러온게 하나의 js파일이 되기 때문에
한 파일이 다른 파일이 가진 자원과 충돌할 수도 있었다.
💡 html파일에서 script파일을 임포트
//사용될 자원이 항상 먼저 와야함
<script src="classedball.js" defer></script>
<script src="classedbutton.js" defer></script>
//사용할 script가 맨 마지막에 와야함
<script src="game1 copy.js" defer></script>
이 충돌을 피하기 위해서는
각각을 모듈화하고 서로 연동시킬 수 있는 방법이 필요하게 되었는데,
이 개념이 ES6에서 등장했다.
방법은 간단하다.
html에서 script를 불러올 때 module이라고 표시를 해주는 방법으로 구현할 수 있다.
export하고 싶은 함수 앞에 위의 사진과 같이 export를 적어주면 되는데,
여러 개를 export하고 싶다면 export할 객체를 만들어서
한 번에 처리할 수 있다.
(export를 꼭 각각의 함수 앞에 모두 쓸 필요는 없다. 그러나 각각 써주는 것이 일반적!)
다음을 코드로 한 번 구현해보자.
💡 game1이라는 js 폴더에서 moule.js의 기능을 호출해보자.
==========game1.js==============
import { test, test1 } from './modules/lib1.js'
test();
==========lib1.js==============
function test() {
console.log("lib1 module test");
}
function test1() {
console.log("lib1 module test1");
}
export { test, test1 };
⭕ 출력결과:
html에서 별도로 module설정을 하지 않고 다음을 출력하면 오류가 날 것이다.
(내가 겪었던 경험)

오류가 나지 않게 html에도 type을 잘 설정해보자.
💡 game1이라는 js 폴더에서 moule.js의 기능을 호출해보자.
==========index.html==============
//html문서에서 type을 "module"로 설정
<script type="module" src="game1 copy.js" defer></script>
==========game1.js==============
//import하기
import { test, test1 } from './modules/lib1.js'
test();
==========lib1.js==============
function test() {
console.log("lib1 module test");
}
function test1() {
console.log("lib1 module test1");
}
//export하기
export { test, test1 };
⭕ 출력결과:
html에서 module을 설정하니 정상적으로 잘 출력되었다!
🚨 혹시라도 공이나 버튼에 문제가 있다면 ctx를 매개변수로 전달하지 않았을 것이다.

만약 서로 다른 모듈에서 같은 이름의 기능을 호출한다면 어떻게 될까?
💡 다음을 출력하면 어떤 것이 호출될까?
import { test, test1 } from './modules/lib1.js';
import { test, test1 } from './modules/lib2.js';
test();
⭕ 출력결과:
같은 이름이라서 오류가 뜬다.

그러면 같은 이름의 기능을 호출했을 때 어떻게 오류를 피할 수 있을까?
💡 부르는 쪽에서 이름을 바꿔보자.
import { test as lib1Test, test1 as lib1Test1 } from './modules/lib1.js';
import { test, test1 } from './modules/lib2.js';
lib1Test();
test();
⭕ 출력결과:
위와 같이 import하는 쪽에서 이름을 바꿔서 설정하면
정상적으로 두 개의 기능을 각각 호출할 수 있게 되었다.

#default
보통 export를 할 때는 각각의 기능 앞에 export를 쓰는데
이때 export 뒤에 default를 써주게 되면 부르는 쪽에서
마치 이름을 변수 설정하듯이 쉽게 바꿀 수 있다.
그냥 export하는 함수와 다른 표기법을 아래에서 확인해보자.
💡 default로 설정하면 import할 때 이름을 새로 지정해줄 수 있다.
default로 설정한 것은 따로 이름을 설정하고 : aa
나머지 여집합 애들은 중괄호{} 안에 담아서 넘긴다. : {test1, test2}
import aa, { test1, test2 } from './modules/lib2.js'; lib1Test(); lib1Test1(); aa(); test2();
export할 때 default는 하나만 지정할 수 있다.
두 개를 지정하면 다음과 같은 오류가 뜬다.
💡 defualt를 2개 설정하면?
==========game1 copy.js==============
import { test as lib1Test, test1 as lib1Test1 } from './modules/lib1.js';
import aa, { test1, test2 } from './modules/lib2.js';
lib1Test();
test1();
aa();
test2();
==========lib2.js==============
export default function test() { //default
console.log("lib2 module test");
}
export function test1() {
console.log("lib2 module test1");
}
export default function test2() { //default
console.log("lib2 module test2");
}
//export는 불러올 함수 앞에 각각 쓰는 것이 일반적
// export { test, test1 };
⭕ 출력결과:
default를 2개 설정할 수는 없다.
한 스크립트 파일의 기능 및 속성을 export할 때
default로 설정할 수 있는 것은 단 하나라는 점을 잘 기억해두자.

또 default로 설정한 녀석을 일반 객체 보내듯이 하면 에러가 난다는 점도 기억해두자.
💡 Ball을 export할 default로 사용하였다.
==========game1 copy.js==============
//이름을 지정 안하고 객체형태로 받음
import { Ball } from './classedball.js';
==========classedBall.js==============
export default class Ball {} //default
⭕ 출력결과:
일반 객체 전달하듯이 {Ball}이라고 하니 에러가 난다.
default는 별도의 이름을 지정해주어야 한다.

(+번외) 그런데 이 줄이 좀 불편하지 않은가?
함수이름이 겹치니까 각각을 as를 통해서 새로 이름을 지어줬던 부분이다.
💡 각각의 함수에 이름을 별도로 지정했다.
//lib1.js와 lib2.js에서 불러올 함수의 이름이 동일해서
//import하는 쪽에서 lib1의 함수들에 as를 이용해서 이름을 지정해주었다.
import bb, { test1 as lib1Test1, test2 as lib1Test2, data } from './modules/lib1.js';
import { test1, test2 } from './modules/lib2.js';
문자를 이용하면 이것도 간단하게 처리할 수 있다.
애스터리스크(* )를 사용하면 export하는 객체(함수포함)를 한 번에 불러올 수 있다.
불러오고 난 뒤에는 lib1.test()와 같은 식으로 필요한 함수나 데이터를 호출하면
test()라는 기존의 함수명을 그대로 사용할 수 있다.
그러나 default는 별도로 이름을 지정해주어야 한다.
💡 문자(* )을 사용해서 간소화 표현을 해보자.
==========game1 copy.js==============
import bb, * as lib1 from './modules/lib1.js'; //default는 별도로 이름 써야함
bb();
lib1.test1();
test2();
console.log(lib1.data.x);
==========lib1.js==============
export default function test() { //함수
console.log("lib1 module test");
}
export function test1() { //함수
console.log("lib1 module test1");
}
export let data = { x: 50, y: 100 }; //데이터
⭕ 출력결과:
* as lib1을 통해서 이름이 겹쳐도 상관없이 함수를 불러올 수 있게 되었다.
단, default는 별도로 이름을 꼭 지정(bb)해줘야 한다.
#데이터를 노출할 때
그렇다면 함수만 export할 수 있을까?
아니다. 데이터도 다른 스크립트 파일로 export할 수 있다.
단, 이때 형식은 일반 객체형태로 보내준다. 중괄호에 담아서{}
💡 함수, 클래스 말고 데이터도 export 해보자!
==========game1 copy.js==============
import aa, { test1, test2, data } from './modules/lib2.js';
console.log(data.x)
==========lib2.js==============
export default function test() {
console.log("lib2 module test");
}
export function test1() {
console.log("lib2 module test1");
}
export function test2() {
console.log("lib2 module test2");
}
export let data = { x: 20, y: 10 };
⭕ 출력결과:
정상적으로 20이라는 결과가 나온다!
#window 변수는 import가 필요 없을까?
혹시 만약 다른 js파일에서 window 객체를 생성하면 import 없이 읽어올 수 있을까?
정답은 NO..! define되지 않았다는 오류가 발생한다.
실제로 코드로 찍어보자.
💡 window 객체로 선언하면 다른 js파일에서 읽을 수 있을까?
==========game1 copy.js==============
console.log(count);
==========config.js==============
window.count = 10;
⭕ 출력결과:
window.count로 선언했을지라도 다른 파일에서는 읽어올 수 없다.

아무리 window객체라고 할지라도 사용하려는 쪽에서 import를 해줘야 한다.
대신 import할 때 객체명을 적을 필요가 없다. 경로만 적어주면 된다.
💡 다른 js파일에서 데이터(변수)를 읽어와보자.
==========game1 copy.js==============
import './modules/config.js'
console.log(count);
==========config.js==============
window.count = 10;
⭕ 출력결과:
정상적으로 10이 출력된다.

💙 마치며
1.
-잊지 않기 위해 쓰는 글-
class의 타입은 function이고,
사실 class의 메소드들은 다 prototype안에 들어가지만
표기법이 class안에 기재하는 식으로 바뀌었을 뿐이다.
2.
모듈화 한 스크립트파일들은
class형태로 import/export하면
그 효과가 배가 되는 것 같다.
3.
default는 한 스크립트 파일에서 1개만 가능하다.
잊지말자!