...
require()
CommonJS 방식으로 모듈을 내보낼 때는 ES6처럼 명시적으로 선언하는 것이 아니라 특정 변수나 그 변수의 속성으로 내보낼 객체를 세팅해줘야 합니다.
특히, 제일 햇갈리는 부분이 exports 변수와 module.exports 변수를 상황에 맞게 잘 사용해야 한다는 점입니다.
기본적으로 다음 2가지 규칙만 기억하면 됩니다
- 여러 개의 객체를 내보낼 경우, exports변수의 속성으로 할당합니다.
- 딱 하나의 객체를 내보낼 경우, module.exports 변수 자체에 할당합니다.
단, 객체를 묶어서 여러개 값을 export할수 있습니다.
노드 복수 객체 내보내기/불러오기
내보내기
아래는 미국과 캐나다 달러를 상호 변환해주는 자바스크립트 예제 코드입니다.
이 파일에는 3개의 함수가 있는데 아래 2개의 함수만 다른 파일에서 접근할 수 있도록 내보내기를 하였습니다.
exports 변수의 속성으로 내보낼 함수들을 세팅합니다.
/* currency-functions.js */
const exchangeRate = 0.91;
function roundTwoDecimals(amount) {
return Math.round(amount * 100) / 100;
}
const canadianToUs = function (canadian) {
return roundTwoDecimals(canadian * exchangeRate);
};
function usToCanadian(us) {
return roundTwoDecimals(us / exchangeRate);
}
exports.canadianToUs = canadianToUs; // 내보내기 1
exports.usToCanadian = usToCanadian; // 내보내기 2
불러오기
위에서 내보낸 여러 개의 객체는 require 키워드를 통해 한 번에 불러와 변수에 할당할 수 있으면, 그 변수를 통해서 내보낸 객체에 접근할 수 있습니다.
/* test-currency-functions.js */
const currency = require("./currency-functions");
console.log("50 Canadian dollars equals this amount of US dollars:");
console.log(currency.canadianToUs(50));
console.log("30 US dollars equals this amount of Canadian dollars:");
console.log(currency.usToCanadian(30));
실행 결과
50 Canadian dollars equals this amount of US dollars:
45.5
30 US dollars equals this amount of Canadian dollars:
32.97
노드 단일 객체 내보내기
내보내기
이번에는 예제 코드를 살짝 수정하여 아래 두 개 함수를 메서드로 객체로 묶어서 내보내기를 하였습니다.
내보낼 객체를 module.exports 변수에 할당해주면 됩니다.
/* currency-class.js */
const exchangeRate = 0.91;
// 안 내보냄
function roundTwoDecimals(amount) {
return Math.round(amount * 100) / 100;
}
// 내보내기
const obj = {};
obj.canadianToUs = function (canadian) {
return roundTwoDecimals(canadian * exchangeRate);
};
obj.usToCanadian = function (us) {
return roundTwoDecimals(us / exchangeRate);
};
module.exports = obj;
불러내기
위에서 내보낸 하나의 객체는 require 키워드를 통해 변수에 할당할 수 있으며, 그 변수를 통해서 일반 객체에 접근하는 것 처럼 속성에 세팅되어있는 함수에 접근할 수 있습니다.
/* test-currency-object.js */
const currency = require("./currency-object");
console.log("50 Canadian dollars equals this amount of US dollars:");
console.log(currency.canadianToUs(50));
console.log("30 US dollars equals this amount of Canadian dollars:");
console.log(currency.usToCanadian(30));
실행 결과
50 Canadian dollars equals this amount of US dollars:
45.5
30 US dollars equals this amount of Canadian dollars:
32.97
require 디렉토리
require 함수의 인수에는 파일뿐만 아니라 디렉터리를 지정할 수도 있습니다.
예를 들어 다음과 같은 디렉터리 구조의 경우를 살펴보죠.
project/
├── app.js
└── module/
├── index.js
├── calc.js
└── print.js
아래과 같이 모듈을 명시하지 않고 require 함수를 호출하면 해당 디렉터리의 index.js을 로드하게 됩니다
const myModule = require('./module');
이때 로드되는 index.js 내에서 calc.js과 print.js를 require하면 한번의 require로 alc.js과 print.js의 모든 기능을 사용할 수 있겠죠.
module/calc.js
module.exports = {
add (v1, v2) { return v1 + v2 },
minus (v1, v2) { return v1 - v2 }
};
module/print.js
module.exports = {
sayHello() { console.log('Hi!') }
};
module/index.js
module.exports = {
calc: require('./calc'),
print: require('./print')
};
app.js (사용)
const myModule = require('./module');
// module/calc.js의 기능
const result = myModule.calc.add(1, 2);
console.log(result);
// module/print.js의 기능
myModule.print.sayHello();
다음은 같은 원리에 다른 모듈 함수 예제 그림입니다.
즉시 실행하기
변수에 대입하지 않고 require만 쓰면 바로 실행하는 결과가 됩니다.
require('./var.js'); // var.js의 코드를 바로 실행
순환 참조 (무한루프)
실수로 두 개의 모듈이 서로를 require하는 상황을 조심해야 합니다.
- dep1이 dep2를 require하고,
- dep2가 dep1을 require 함.
- dep1의 module.exports가 함수가 아니라 빈 객체가 됨(무한 반복을 막기 위해 의도됨)
- 순환참조하는 상황이 나오지 않도록 하는 게 좋음.
require ⚔️ import (CommonJs와 ES6) 차이
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.