Node.js 공부를 시작하며 모듈
이라는 단어를 계속해서 접하고 있다. 모듈의 사전적 의미는 아래와 같다.
Module
1. 모듈, 교과목 단위(특히 영국 대학에서 한 교육 과정의 일부가 되는 단위)
2. 컴퓨터 모듈(특정 기능을 하는 컴퓨터 시스템이나 프로그램의 단위)
3. 모듈, 조립 부품(기계·가구·건물 등을 구성하는 규격화된 부품)
4. 모듈(우주선의 본체에서 떨어져 나와 독립된 기능을 하는 작은 부분)
작은 부분, 단위, 부품을 모듈이라고 하는 것은 알겠는데 그럼 코드를 작성할 때 말하는 모듈
의 의미는 무엇인지 궁금해졌다.
Javascript.info에 따르면 분리된 파일 각각을 모듈이라고 하고, 단지 파일 하나라고 생각하면 된다고 한다. 따라서 스크립트 하나는 모듈 하나를 의미한다. w3schools에 따르면 'JavaScript modules allow you to break up your code into separate files. This makes it easier to maintain the code-base. JavaScript modules rely on the import
and export
statements.' 이라고 모듈을 설명하고 있ek.
westudy의 자료를 통해 조금 더 알아보자면, 코드의 조각으로 여러 모듈이 조합되어 하나의 소프트웨어를 이룬다고 한다. 즉 프로그램을 만들 때 코드를 잘 모듈화해서 만들게 되면 유지보수하기 쉬운 구조로 시스템을 만들 수 있다.
모듈화에 필요한 것은 크게 세 가지이다.
- 모든 모듈은 자신만의 독립적인 실행 영역이 있어야 한다.
- 전역변수와 지역변수를 분리하는 것을 의미한다. 서버 사이드 JavaScript의 경우에는 파일마다 독립적인 파일 스코프가 있기 때문에 파일 하나에 모듈 하나를 작성하는 방법으로 독립적인 실행 영역을 만든다.
- 모듈을 외부에서 사용할 수 있도록 공개한다.
- Node.js에서는
exports
라는 전역 객체를 이용해서 정의한다.
- 모듈을 사용하는 영역에서는
require()
함수를 이용해서 모듈을 불러온다.
모듈은 module.exports
또는 exports
객체를 통해 정의하고 외부로 공개하고, 공개된 모듈은 require()
함수를 사용하여 임포트한다.
exports
객체의 프로퍼티 또는 메소드를 정의하는 방법// calculator.js
const initialNumber = 0
exports.add = (x, y) => initialNumber + x + y; // export 객체에 add method 정의
exports.substract = (x, y) => initialNumber + x - y; // export 객체에 substract method 정의
위 코드에서 calculator.js는 독립적인 파일 스코프를 갖는 모듈이다. calculator 모듈에 add와 substract를 exports 객체의 메소드로 정의하였다.
변수 initialNumber는 calculator 모듈에서만 유효한 private 변수가 되고, add와 substract 메소드는 외부에 공개되어 필요한 곳에서 사용할 수 있다. 따라서 require()
함수를 사용하여 add와 sub 함수가 필요한 곳에서 임의의 이름으로 calculator 모듈을 import 할 수 있다.
// main.js
const calculator = require("./calculator.js");
console.log(`1 + 5 = ${calculator.add(1, 5)}`);
console.log(`1 - 5 = ${calculator.subtract(1, 5)}`);
이때 require
함수 호출 결과 calculator 모듈은 객체 형태로 반환되어 calculator 변수에 담기게 됩니다 . 따라서 calculator.add, calculator.sub과 같은 형식으로 공개된 calculator 모듈을 참조한다. 아래의 코드를 보면 정상적으로 분리된 모듈을 참조해서 사용할 수 있음을 알 수 있다.
$ node main
1 + 5 = 6
1 - 5 = -4
exports
객체는 여러 개의 속성과 메소드를 정의할 수 있는 반면 module.exports
에는 하나의 객체만 할당할 수 있다.
// calculator.js
const initialNumber = 0
function add(a, b) {
return a + b;
}
function substract(a, b) {
return a - b;
}
module.exports = {
add,
substract
}
calculator 모듈의 module.exports
에는 하나의 객체만 할당되었다.
// main.js
const calculator = require("./calculator.js");
console.log(`1 + 5 = ${calculator.add(1, 5)}`);
console.log(`1 - 5 = ${calculator.substract(1, 5)}`);
require 함수를 통해 calculator 모듈을 임포트하여 calculator 변수에 할당했습니다. 아래와 같이 구조분해 할당을 활용해서 아래와 같이 import해서 사용할 수도 있다.
// 구조분해 할당을 활용해서 import하는 방법
// main.js
const {add, substract} = require("./calculator.js");
console.log(`1 + 5 = ${add(1, 5)}`);
console.log(`1 - 5 = ${substract(1, 5)}`);
exports
는 module.exports
를 참조하고 있기 때문에 exports
는 module.exports
와 같다고 보아도 무방하다. 공식문서에서도 exports
는 module.exports
의 축약형(shortcut)이라고 언급되어있다. 그래도 혼란스럽다면, module.exports
를 사용하자.