수성컴전자방입니다. “Divide and Conquer”라는 말이 있습니다. 문제가 있을 때 분할하여 정복하라는 것입니다. 오늘은 JavaScirpt에서 파일을 분할하여 모듈화해 보겠습니다. ES2015에서 import, export 문법이 추가되었으므로 해당 문법을 사용하겠습니다.
목차
1. named export와 named import
1.1. 변수/함수/클래스 정의할 때 named export 하기
1.2. 몰아서 named export 하기
1.3. 요소별 named import
1.4. 다른 이름으로 import
1.5. 모듈 전체 import
2. default export와 default import
2.1. default export
2.2. default import
3. named와 default 혼용 예제
3.1. func.js
3.2. main.js
4. HTML에서 JavaScript 불러오기
5. 글 마무리
6. 참고 자료
1. named export와 named import
예제는 func.js에 함수들을 넣고, main.js에서 불러와서 쓰겠습니다. func.js와 main.js는 한 폴더 안에 있습니다. named export는 1.1~1.2절 중 한 가지 방법을 택하고, named import는 1.3~1.5절 중 한 가지 방법을 택하시면 됩니다.
1.1. 변수/함수/클래스 정의할 때 named export 하기
▼func.js
export function add(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1+num2;
}
export function subtract(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1-num2;
}
[Line 1, 13]
export할 변수/함수/클래스 앞에 export를 붙입니다.
1.2. 몰아서 named export 하기
▼func.js
function add(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1+num2;
}
function subtract(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1-num2;
}
export {add, subtract};
[Line 25]
export {add, subtract};
내보낼 변수나 함수, 클래스 등을 배열 형태로 작성합니다.
1.3. 요소별 named import
▼main.js
import {add, subtract} from './func.js';
function runadd(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_add").innerHTML=add(element_a, element_b);
}
function runsub(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_sub").innerHTML=subtract(element_a, element_b);
}
document.getElementById("add").addEventListener("click", runadd);
document.getElementById("sub").addEventListener("click", runsub);
[Line 1 import]
import {add, subtract} from ’./func.js’;
불러올 변수나 함수, 클래스 등을 배열 형태로 작성합니다. 이때 이름은 원래 이름(예제의 경우 func.js에서 선언한 이름)을 씁니다.
from 뒤에 불러올 변수나 함수, 클래스 등이 있는 파일 이름과 확장명을 작성합니다.
[Line 7, 14]
불러온 변수나 함수, 클래스 등을 원래 이름으로 사용하시면 됩니다.
1.4. 다른 이름으로 import
이름이 길거나 복잡한 변수/함수/클래스를 import 할 때 as 키워드를 사용하여 임의의 이름을 지정할 수 있습니다.
▼main.js
import {add as ad, subtract as sub} from './func.js';
function runadd(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_add").innerHTML=ad(element_a, element_b);
}
function runsub(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_sub").innerHTML=sub(element_a, element_b);
}
document.getElementById("add").addEventListener("click", runadd);
document.getElementById("sub").addEventListener("click", runsub);
[Line 1 import]
import {add as ad, subtract as sub} from ’./func.js’;
원래의 이름 뒤에 as 원하는 이름을 작성하시면 됩니다.
예제에서는 add와 subtract를 import 하면서 add라는 이름 대신에 ad로, subtract 대신에 sub로 바꾸었습니다.
[Line 7, 14]
불러온 변수나 함수, 클래스 등을 바꾼 이름으로 사용하시면 됩니다.
1.5. 모듈 전체 import
내보내진 모듈 전체를 하나의 객체로 불러올 수 있습니다. 이때 객체 이름을 지어야 합니다.
▼main.js
import * as cal from './func.js';
function runadd(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_add").innerHTML=cal.add(element_a, element_b);
}
function runsub(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_sub").innerHTML=cal.subtract(element_a, element_b);
}
document.getElementById("add").addEventListener("click", runadd);
document.getElementById("sub").addEventListener("click", runsub);
[Line 1 import]
import * as cal from ’./func.js’;
모듈 전체를 import 할 때는 *을 사용합니다. import 뒤에 * as 임의의 객체명을 작성하시면 됩니다.
[Line 7, 14]
7행으로 예를 들겠습니다.
document.getElementById(“result_add”).innerHTML=cal.add(element_a, element_b);
불러온 변수나 함수, 클래스 등을 사용할 때는 1행에서 지정한 이름.원래 이름으로 사용합니다.
2. default export와 default import
예제는 func.js에 함수들을 넣고, main.js에서 불러와서 쓰겠습니다. func.js와 main.js는 한 폴더 안에 있습니다.
2.1. default export
파일 당 하나의 default export만 있어야 합니다.
문단 제목은 ‘default export’이지만 코딩할 때는 export default라고 씁니다.
▼func.js
export default function add(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1+num2;
}
[Line 1]
export할 변수/함수/클래스 앞에 export default를 붙입니다.
2.2. default import
▼main.js
import ad from './func.js';
function runadd(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_add").innerHTML=ad(element_a, element_b);
}
document.getElementById("add").addEventListener("click", runadd);
[Line 1 import]
import ad from ’./func.js’;
default import 할 때는 원하는 이름으로 import 하시면 됩니다.
[Line 7]
불러온 변수나 함수, 클래스 등을 사용할 때는 1행에서 정한 이름으로 사용하시면 됩니다.
3. named와 default 혼용 예제
하나의 파일에서 named export와 default export를 둘 다 사용할 수 있습니다.(단, default export는 1개만)
3.1. func.js
export default function add(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1+num2;
}
export function subtract(a, b){
if (isNaN(a) || isNaN(b)) {
alert("숫자만 입력하세요!");
return;
}
let num1=Number(a);
let num2=Number(b);
return num1-num2;
}
add 함수는 default export로, subtract 함수는 named export로 했습니다.
3.2. main.js
import ad, {subtract} from './func.js';
function runadd(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_add").innerHTML=ad(element_a, element_b);
}
function runsub(){
let element_a=document.getElementById("a").value;
let element_b=document.getElementById("b").value;
document.getElementById("result_sub").innerHTML=subtract(element_a, element_b);
}
document.getElementById("add").addEventListener("click", runadd);
document.getElementById("sub").addEventListener("click", runsub);
[Line 1 import]
import ad, {subtract} from ’./func.js’;
default import 할 것을 먼저 적고, 그 뒤에 named import 할 것을 적습니다.
4. HTML에서 JavaScript 불러오기
1~3장 중 한 가지 방법으로 JavaScript 코드를 작성했고, index.html과 main.js, func.js가 모두 한 폴더 안에 있다고 가정하겠습니다.
(단, 2장 예제 코드를 그대로 사용했을 경우 빼기 기능은 작동하지 않습니다.)
▼index.html
<!DOCTYPE html>
<html>
<head>
<title>JS 모듈 테스트</title>
<script src="main.js" type="module"></script>
</head>
<body>
<header>
<h1>JavaScript 모듈 테스트</h1>
</header>
<section>
<input type="text" id="a"/>와 <input type="text" id="b"/><br>
더하기: <span id="result_add"></span><br>
빼기: <span id="result_sub"></span><br>
<input type="button" value="더하기" id="add"><br><!--더하기는 1~3장 예제 코드 모두 가능-->
<input type="button" value="빼기" id="sub"><br><!--빼기는 1, 3장 예제 코드에서만 가능-->
</section>
</body>
</html>
[Line 6]
<script src=”main.js” type=”module”></script>
src는 main.js만 연결합니다. func.js는 이미 main.js에서 import했기 때문에 index.html과 따로 연결하지 않아도 됩니다.
type=”module” 속성을 반드시 사용하여 해당 스크립트가 모듈이라는 것을 웹 브라우저에게 알려 주어야 합니다.
JavaScript는 모듈 기능 없이 사용할 경우 변수, 함수들이 전역적으로 선언됩니다(같은 파일에 있지 않아도). 그러나 type=”module” 속성을 사용할 경우 변수, 함수들이 지역적으로 선언됩니다. 따라서 HTML에서 onclick으로 JavaScript 모듈의 함수를 호출할 수 없습니다. 이것을 해결할 방법은 2가지가 있습니다.
방법1) JavaScript 코드에 window.함수명=함수; 코드를 추가하여 전역함수로 선언
방법2) JavaScript 코드에서 JavaScript 문법인 addEventListener 사용(권장)
이 글에서는 addEventListener를 사용해 보겠습니다.
▼main.js
//...
document.getElementById("add").addEventListener("click", runadd); //더하기는 1~3장 예제 코드 모두 가능
document.getElementById("sub").addEventListener("click", runsub); //빼기는 1, 3장 예제 코드에서만 가능
//...
document.getElementById(“버튼id”).addEventListener(“click”, 실행할함수이름);
이와 같이 사용하시면 됩니다.
모듈(import, export 기능)은 로컬 파일(file:// 프로토콜)에서 작동하지 않습니다. HTTP 또는 HTTPS로 돌려야 합니다. Visual Studio Code를 사용하신다면 Live Server 확장(관련 글)을 사용하시면 편리합니다.
그러면 정상 작동하는 것을 보실 수 있을 것입니다.
5. 글 마무리
제 글을 읽어 주셔서 감사합니다. 다음에 만나요!
6. 참고 자료
1) Playdaddy. 2022. “[JavaScript]자바스크립트 처리 파일 분할하기 (ES 모듈)”, Playdaddy. (2024. 10. 26. 방문). https://stonefree.tistory.com/451
2) Naerrow. 2024. “[기초]Javascript export, import 모듈”, MY DEV STACK. (2024. 10. 26. 방문). https://naerrowstory.tistory.com/25
3) 인파. 2021. “[JS] 📚 모듈 사용하기 import / export 완벽 💯 정리”, Inpa Dev. (2024. 10. 26. 방문). https://inpa.tistory.com/entry/JS-📚-모듈-사용하기-import-export-정리
4) Ali Nasiri 외 2명. 2024. “Not reading the function in a JavaScript Module file, by calling onclick in the html document”, stackoverflow. (2024. 10. 26. 방문). https://stackoverflow.com/questions/78251387/not-reading-the-function-in-a-javascript-module-file-by-calling-onclick-in-the
5) mdn web docs. n. d. “EventTarget: addEventListener() method”, mdn web docs. (2024. 10. 26. 방문). https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
6) 노경환. n. d. “addEventListener 사용법”, 기억보다 기록을. (2024. 10. 26. 방문). https://kyounghwan01.github.io/blog/JS/JSbasic/addEventListener/