모듈 정의
프로그램을 구성하는 내부의 코드가 기능별로 나뉘어져 있는 형태
Module 사용 시
- 코드의 재사용성이 증가한다.
- 코드의 관리가 편해진다.
- 코드를 모듈화하는 기준이 명확해야 한다.
표준 모듈
모듈을 사용하기 위해서는 모듈을 인식하는 Module system 과 모듈을 다루는 키워드가 제공되어야 한다.
Module System
- CommonJS (Node.js)
- ESM (ECMAScript 2015~)
Module Keywords
- 가져오기 - 모든 객체를 참조하는 형태
- 내보내기 - 1. 한 곳으로 내보내기 2. 개별적으로 내보내기
CommonJS
- 가져오기: require (모듈의 경로)
- 내보내기: module.exports
module.exports = {...}
: 내보낼 값들을 한 객체 안에 할당해서 내보내는 방법module.exports = 값
: 상수나 함수를 바로 할당하여 내보내는 방법module.exports.키_이름 = 값
: module.exports 에 직접 키를 지정하고 키마다 각각의 값을 할당해서 내보내는 방법exports.키_이름 = 값
: module.exports 의 출력형
⭐ 예제: 원의 넓이를 구하는 코드 (Common JS)
원의 넓이를 구하는 코드는 다음과 같이 나누어서 구한다.
1. 원의 넓이를 구하는 공식
2. PI 정의
3. 공식을 통해 결과 얻기
const PI = 3.14;
const getCircleArea = r => r * r * PI;
const result = getCircleArea(2);
console.log(result);
위와 같이 하나의 파일에 코드를 작성할 수 있지만, 프로젝트가 커지게 되면 하나의 파일에서 코드를 읽고 해석하는데 시간이 오래걸릴 뿐더러 변경해야 할 일이 있을 때 값을 관리하기에도 어려움이 있다.
따라서 파일을 분리하여 모듈로 내보내기/가져오기를 통해 다른 파일에서 가져와서 접근할 수 있도록 만들어준다.
예제의 넓이를 구하는 공식 및 파이의 정의와 공식을 통해 결과를 얻는 파일로 나누어주었다.
mathUtil.js - 원의 넓이를 구하는 공식 파일
const PI = 3.14;
const getCircleArea = r => r * r * PI;
// 한 곳으로 내보내기
module.exports = {
PI,
getCircleArea
}
// 개별적으로 내보내기
exports.PI = PI;
exports.getCircleArea = getCircleArea;
index.js - 원의 넓이를 구하는 결과 파일
const mathUtil = require('./mathUtil') // 가져오기 - 파일전체
const { getCircleArea } = require('./mathUtil') // 가져오기 - destructuring
const result = getCircleArea(2);
console.log(result);
require 경로 작성 시 node.js 환경에서는 모듈의 기본 확장자가 js 이므로 확장자명은 생략했다.
모듈을 가져올 때 해당 파일의 모든 값이 필요한 것이 아니므로, 필요한 값만 뽑아서 변수에 할당하는 destructing 을 통해 넓이를 구하는 함수만 가져왔다.
ESM
- 가져오기:
import 모듈_이름 from 모듈_위치
- 내보내기:
export
또는exprot default
🚨 export 와 export default 차이점
export default 로 내보낼 때는 객체 이름을 지정해주고 이름을 통해서 내보내는 기능에 접근하는 방식으로 사용해야 한다.
mathUtil.js
const PI = 3.14;
const getCircleArea = r => r * r * PI;
export default {
PI,
getCircleArea
}
❌아래처럼 코드를 작성하면 오류가 난다.
import { getCircleArea } from "./mathUtil";
const result = getCircleArea(2);
console.log(result);
✅
import mathUtil from "./mathUtil";
const result = mathUtil.getCircleArea(2);
console.log(result);
Node.js 는 기본적으로 CommonJS 를 따르기 때문에 ESM 을 사용하기 위해서는 외부 모듈을 사용하여 접근할 수 있도록 해야한다. (node 명령어를 실행할 때 실행하는 파일의 모듈 표준 중에 CommonJS 외에도 다른 모듈 표준(esm)도 해석할 수 있도록 설정해준다.)
npm install esm
node -r esm index.js
⭐ 예제: 원의 넓이를 구하는 코드 (ESM)
CommonJS 에서 적용한 원의 넓이를 구하는 공식을 ESM 에서 작성하였다.
mathUtil.js - 원의 넓이를 구하는 공식 파일
const PI = 3.14;
const getCircleArea = r => r * r * PI;
export {
PI,
getCircleArea
}
index.js - 원의 넓이를 구하는 결과 파일
import { getCircleArea } from "./mathUtil";
const result = getCircleArea(2);
console.log(result);
Module 종류
- Built-in Core Module (ex. Node.js module) - 내장되어 있는 코어 모듈
- Community-based Module (ex. NPM)
- npmm CLI 를 사용해서 접근할 수 있다. ( ex.
npm install ModuleName
)
- npmm CLI 를 사용해서 접근할 수 있다. ( ex.
- Local Module (특정 프로젝트에 정의된 모듈)
예제
도형의 넓이를 구하는 코드를 기능별로 모듈화하기
readline
: node.js 에서 제공하는 내장 모듈. 사용자로부터 입력을 받을 수 있게 여러 기능을 제공하는 모듈
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
rl.question('원하는 도형을 작성해주세요 : ', input => {
console.log(input);
rl.close();
})
question
메서드는 사용자에게 입력을 받기 전에 입력과 관련된 정보를 전달하고 입력된 데이터를 콜백함수로 다룰 수 있게 한다.- 첫번째 파라미터: 어떤 입력을 해야하는지 정보를 제공하는 문자열
- 두번째 파라미터: 사용자 입력이 발생하면 실행되는 콜백함수를 받는다.
- 콜백함수에서는 입력받은 정보를 인자로 전달받는다.
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const { getCircleArea, getSquareArea } = require('./mathUtil');
rl.question(
'넓이를 구하고자 하는 도형의 종류를 입력해주세요. ( 정사각형, 원 ) : ',
figure => {
console.log(`선택한 도형: ${figure}`);
switch (figure) {
case '정사각형':
rl.question('변의 길이를 입력해주세요 : ', input => {
console.log(`입력받은 값: ${input}`);
console.log(`정사각형의 넓이는 : ${getSquareArea(input)} 입니다.`);
rl.close();
});
break;
case '원':
rl.question('반지름의 길이를 입력해주세요 : ', input => {
console.log(`입력받은 값 : ${input}`);
console.log(`원의 넓이는 : ${getCircleArea(input)} 입니다.`);
rl.close();
});
break;
default:
console.log(
"지원되지 않는 도형입니다. '정사각형' 또는 '원'을 입력해주세요. \n커맨드 라인을 종료합니다."
);
rl.close();
}
}
);
모듈화
index.js 에서 중복되는 console 결과 입력창을 분리해서 모듈화하려고 한다.
// 중복되는 consosle 값들을 분리
const logInput = input => `입력받은 값: ${input}`;
const logResult = (figure,result) => `${figure}의 넓이는 : ${result} 입니다`;
const logFigureError = "지원되지 않는 도형입니다. '정사각형' 또는 '원'을 입력해주세요. \n커맨드 라인을 종료합니다.";
module.exports = {
logInput,
logResult,
logFigureError
}
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const { getCircleArea, getSquareArea } = require('./mathUtil');
const { logFigureError, logInput, logResult } = require('./log');
rl.question(
'넓이를 구하고자 하는 도형의 종류를 입력해주세요. ( 정사각형, 원 ) : ',
figure => {
console.log(`선택한 도형: ${figure}`);
switch (figure) {
case '정사각형':
rl.question('변의 길이를 입력해주세요 : ', input => {
console.log(logInput(input));
console.log(logResult(figure, getSquareArea(input)));
rl.close();
});
break;
case '원':
rl.question('반지름의 길이를 입력해주세요 : ', input => {
console.log(logInput(input));
console.log(logResult(figure, getCircleArea(input)));
rl.close();
});
break;
default:
console.log(logFigureError);
rl.close();
}
}
);