노드는 코드를 모듈로 만들 수 있다는 점에서 브라우저의 자바스크립트와는 다르다.
모듈이란 특정한 기능을 하는 함수나 변수들의 집합을 말한다.
ex) 수학에 관련된 코드들만 모아서 모듈을 하나 만들 수 있다.
모듈로 만들어두면 여러 프로그램에 해당 모듈을 재사용할 수 있다.
CommonJS 모듈은 표준 자바스크립트 모듈은 아니지만 노드 생태계에서 가장 널리 쓰이는 모듈이다.
아래 소스 코드에서 변수를 두 개 선언했고, module.exports에 변수들을 담은 객체를 대입했다.
다른 파일에서 이 파일을 불러오면 module.exports에 대입된 값을 사용할 수 있다.
const odd = 'CJS 홀수입니다.';
const even = 'CJS 짝수입니다.';
module.exports = {
odd,
even,
}
require 함수 안에 불러올 모듈의 경로를 적는다.
파일 경로에서 js나 json 같은 확장자는 생략할 수 있다.
var.js에서 변수를 불러온 뒤, 숫자의 홀짝을 판별하는 함수를 선언했다.
const { odd, even } = require('./var');
function checkOddOrEven(num) {
if (num % 2) {
return odd;
}
return even;
}
module.exports = checkOddOrEven;
index.js는 var.js와 func.js를 모두 참조했다.
var.js가 func.js와 index.js에 두 번 쓰이는 것처럼, 모듈 하나가 여러 개의 모듈에 사용될 수 있다.
const { odd, even } = require('./var');
const checkNumber = require('./func');
function checkStringOddOrEven(str) {
if (str.length % 2) {
return odd;
}
return even;
}
console.log(checkNumber(10));
console.log(checkStringOddOrEven('Hello'));
지금까지 모듈을 만들 때 module.exports만 사용했는데, module 객체 말고 exports 객체로도 모듈을 만들 수 있다.
module.exports로 한 번에 대입하는 대신, 각각의 변수를 exports 객체에 하나씩 넣는다.
exports.odd = 'CJS 홀수입니다.';
exports.even = 'CJS 짝수입니다.';
이번에는 모듈을 불러오는 require는 함수이고, 함수는 객체이므로 require 객체로서 속성을 몇 개 갖고 있다.
그중에서 require.cache와 require.main을 알아보겠다.
아래 예제에서 알아야 할 점은 require가 반드시 파일 최상단에 위치할 필요가 없고, module.exports도 최하단에 위치할 필요가 없다.
console.log('require가 가장 위에 오지 않아도 됩니다.');
module.exports = '저를 찾아보세요.';
require('./var');
console.log('require.cache 입니다.');
console.log(require.cache);
console.log('require.main 입니다.');
console.log(require.main === module);
console.log(require.main.filename);
모듈을 사용할 때 주의해야 할 점이 있다. 만약 두 모듈 dep1과 dep2가 있고 이 둘이 서로를 require 한다면 어떻게 될까?
const dep2 = require('./dep2');
console.log('require dep2', dep2);
module.exports = () => {
console.log('dep2', dep2);
};
const dep1 = require("./dep1");
console.log('require dep1', dep1);
module.exports = () => {
console.log('dep1', dep1);
}
const dep1 = require('./dep1');
const dep2 = require('./dep2');
dep1();
dep2();
실행하면 dep1의 module.exports가 함수가 아니라 빈 객체로 표시된다. 이러한 현상을 순환 참조라고 한다.
ECMAScript 모듈
ECMAScript 모듈은 공식적인 자바스크립트 모듈 형식이다.
노드에서는 아직까지는 CommonJS 모듈을 많이 쓰긴 하지만, ES 모듈이 표준으로 정해지면서 ES 모듈을 사용하는 비율이 늘어나고 있다.
require와 exports, module.exports가 각각 import, export, export default로 바뀌었다.
파일도 js 대신 mjs 확장자로 변경되었다.
export const odd = 'MJS 홀수입니다.';
export const even = 'MJS 짝수입니다.';
import { odd, even } from './var.mjs';
function checkOddOrEven(num) {
if (num % 2) {
return odd;
}
return even;
}
export default checkOddOrEven;
import { odd, even } from './var.mjs';
import checkNumber from './func.mjs';
function checkStringOddOrEven(str) {
if (str.length % 2) {
return odd;
}
return even;
}
console.log(checkNumber(10));
console.log(checkStringOddOrEven('hello'));
다이내믹 임포트
const a = false;
if (a) {
require('./func');
}
console.log('성공');
dynamic.js에서 require('./func')는 실행되지 않습니다.
이렇게 조건부로 모듈을 불러오는 것을 다이내믹 임포트라고 한다.
const a = true;
if (a) {
const m1 = await import('./func.mjs');
console.log(m1);
const m2 = await import('./var.mjs');
console.log(m2);
}
import는 Promise를 반환하기에 await나 then을 붙여야 한다.
위 코드에서는 async 함수를 사용하지 않았는데, ES 모듈의 최상위 스코프에서는 async 함수 없이도 await 할 수 있다.
'자바스크립트 > NodeJS' 카테고리의 다른 글
[NodeJS] 중요한 내장 객체 알아보기 (0) | 2023.06.27 |
---|---|
[NodeJS] 노드의 내부 구조 (0) | 2023.06.25 |