LHJ

I'm a FE developer.

3.3 모듈로 만들기

05 Aug 2020 » node_book

3.3 모듈로 만들기

노드는 코드를 모듈로 만들 수 있다는 점에서 브라우저의 자바스크립트와는 다릅니다.
모듈이란 특정한 기능을 하는 함수나 변수들의 집합입니다.
예를 들면 수학에 관련된 코드들만 모아서 모듈을 하나 만들 수 있습니다.
자체로도 하나의 프로그램이면서 다른 프로그램의 부품으로도 사용할 수 있습니다.
뒤에 나오는 예제를 보면 이해하기 쉽습니다.

모듈로 만들어두면 여러 프로그램에 해당 모듈을 재사용할 수 있습니다.
자바스크립트에서 코드를 재사용하기 위해 함수로 만드는 것과 비슷합니다.

보통 파일 하나가 모듈 하나가 됩니다.
파일별로 코드를 모듈화할 수 있어 관리하기 편리합니다.

브라우저의 모듈
2015년 자바스크립트에도 import/export라는 모듈 개념이 도입되었습니다.
하지만 브라우저에는 구현되지 않아서 사용할 수 없었습니다.
크롬 60 버전부터 드디어 브라우저에서도 모듈을 사용할 수 있게 되었습니다.
앞으로 점차 더 많은 브라우저가 모듈 시스템을 지원할 것으로 보입니다.

실제로 모듈을 만들어봅시다.
모듈을 만들 때는 모듈이 될 파일과 모듈을 불러와서 사용할 파일이 필요합니다.

var.jsfunc.js, index.js를 같은 폴더에 만듭니다.
먼저 var.js를 작성합니다.

// var.js
const odd = '홀수입니다';
const even = '짝수입니다';

module.exports = {
    odd,
    even,
}

var.js에 변수 두 개를 선언했습니다.
그리고 module.exports에 변수들을 담은 객체를 대입했습니다.
이제 이 파일은 모듈로서 기능합니다.
변수들을 모아둔 모듈이 되는 것이죠.
다른 파일에서 이 파일을 불러오면 module.exports에 대입된 값을 사용할 수 있습니다.

이번에는 var.js를 참조하는 func.js를 작성하겠습니다.

// func.js
const { odd, even } = require('./var');

function checkOddOrEven (num) {
    if (num % 2) { // 홀수면
        return odd;
    }
    return even;
}

module.exports = checkOddOrEven;

require 함수 안에 불러올 모듈의 경로를 적어줍니다.
앞의 예제에서는 같은 폴더 안에 파일을 만들었지만, 다른 폴더에 있는 파일도 모듈로 사용할 수 있습니다.
require 함수의 인자로 제공하는 경로만 잘 지정해주면 됩니다.
파일 경로에서 jsjson 같은 확장자는 생략할 수 있습니다.

예제 코드에서 require 함수로 var.js에 있던 값들을 불러오고 있습니다.
const { odd, even }은 2.1.5절에서 설명한 ES2015+ 문법입니다.
var.jsmodule.exports에 담겨 있던 객체를 불러와 func.js에서 사용하는 모습입니다.

var.js에서 변수를 불러온 뒤, 숫자의 홀짝을 판별하는 함수를 선언했습니다.
그리고 다시 module.exports에 함수를 대입했습니다.
이렇게 다른 모듈(var.js)을 사용하는 파일을 다시 모듈(func.js)로 만들 수 있습니다.
또한, module.exports에는 객체만 대입해야 하는 것이 아니라 함수나 변수를 대입해도 됩니다.

마지막으로 index.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'))

index.js는 var.js와 func.js를 모두 참조합니다.
모듈 하나가 여러 개의 모듈을 사용할 수 있는 것이죠.
또한, var.js가 func.js와 index.js에 두 번 쓰이는 것처럼, 모듈 하나가 여러 개의 모듈에 사용될 수도 있습니다.

모듈로부터 값을 불러올 때 변수 이름을 다르게 지정할 수도 있습니다.
func.js의 checkOddOrEven이 checkNumber라는 이름으로 사용되고 있습니다.

그럼 index.js를 실행해보겠습니다.
결과는 다음과 같습니다.

이렇게 여러 파일에 걸쳐 재사용되는 함수나 변수들을 모듈로 만들어두면 편리합니다.
그러나 모듈이 많아지고 모듈 간의 관계가 얽히게 되면 구조를 파악하기 어렵다는 단점도 있습니다.
노드에서는 대부분의 파일이 다른 파일을 모듈로 사용하고 있으므로 모듈을 만들고 사용하는 방법을 꼭 알아두어야 합니다.


NOTE : ES2015 모듈

ES2015가 도입되면서 자바스크립트도 자체 모듈 시스템 문법이 생겼습니다.
노드의 모듈 시스템과는 문법이 조금 다릅니다.
본문의 func.js를 ES2015 모듈 스타일로 바꿔보겠습니다.

// func.mjs
import {} from './var';

function checkOddOrEven (num) {
    if (num % 2) { // 홀수면
        return odd;
    }
    return even;
}

export default checkOddOrEven;

requiremodule.exportsimport, export default로 바뀌었습니다.
이와 같은 사소한 차이가 있습니다.
노드에서도 9 버전부터 ES2015의 모듈 시스템을 사용할 수 있습니다.
하지만 파일의 확장자를 mjs로 지정해야 하고, 실행 시 node --experimental-modules [파일명]처럼 특별한 옵션을 붙여주어야 하는 제한이 있습니다.

방금 썼던 require 함수느 module 객체는 따로 선언하지 않았지만 사용할 수 있었습니다.
이것이 어떻게 가능할까요?
바로 노드에서 기본적으로 제공하는 내장 객체이기 때문입니다.
다음 절에서 내장 객체에 대해 자세히 알아보겠습니다.