이번 시간에는 자바스크립트 모듈에 대해 이해하고 사용법을 익혀보도록 하겠습니다.

자바스크립트 모듈이란 개발 생산성과 효율성 그리고 편리한 유지보수를 위해 복잡한 코드의 집합들을 업무단위나  제공 기능을 파일 단위로 분리하여
코드 재사용성을 높이기 위한 방식을 말하며 자바스크립트 모듈의 파일단위로 관리하고 확장자는 .js  로 관리됩니다.

각각의 모듈파일안에  변수,함수(기능),클래스등 다양한 기능을 정의하고 다른 모듈 파일에 기능을 공유(노출)하기 위해서는
export,exports,module.exports 라는 방식으로 모듈 파일내의 기능과 속성등을 외부로 제공할수 있으며 특히 노드 백엔드 모듈은  module.exports 또는 exports 내장객체를 통해 외부로 기능을 제공합니다.  

특히 노드 모듈은 특정한 기능들을 제공하는 함수나 변수들의 집합을 말하며 현재 개발중인 모듈이나 자바스크립트 파일에서 다른 모듈의 기능을 불러(참조)와 해당 모듈내에서 제공하는 기능과 속성을 사용(참조)하려면
import 보다는 require란 함수를 통해 다른 모듈의 기능을 참조해 현재 파일에서 기능을 사용할수 있습니다. 

모든 프로그래밍언어에서는 코드의 재사용성을 높이기 위한 수단을 제공하는데 특히 자바스크립트 노드에서는 주로 모듈을 통해 코드들의 관심사의 분리 및 코드 재사용성을 극대화 해주는 기능을 제공합니다. 


아래 예시와 같이 개발자 정의 모듈도 있지만 Node Framework 자체에서 제공해주는 http,fs와 같은 내장 모듈들도 기본적으로  참조하여 사용하는 방법은 동일합니다. 


1) 개발자 정의 노드 모듈 정의하고 기능 내보내기 

VSCode를 오픈하고 여러분의 작업폴더를 파일>폴더열기를 통해 지정합니다.
예시) PS D:\...\NodeJS\Backend\

작업폴더내에 modules 폴더를 하나 만들고 utils1.js,utils2.js 모듈파일과 index.js 파일을 하나 만들겠습니다.
D:\...\NodeJS\Backend\modules\utils1.js
D:\...\NodeJS\Backend\modules\utils2.js
D:\...\NodeJS\Backend\modules\index.js



먼저 utils1.js 모듈 파일내에 아래와 같이 모듈의 기능을 구현하고 몇몇 기능을 외부로 공유합니다.

노드 기반 모듈 파일내에는 상수,변수,함수 등 다양한 유형의 기능을 정의할수 있으며 정의된 기능을 다른 모듈에서 사용하려면 일
반적으로 module.exports ={객체} 또는 exports.속성명 = 변수/기능명 형태 2가지 방식을 이용해
내보내기 하려는 변수,상수,함수를 객체의 속성명으로 정의하고 속성의 값으로 모듈내 정의된 이름을 지정해주면 됩니다.

- utils1.js
A) module.exports 방식으로 모듈내 기능 내보내기 


//모듈내 변수나 상수값을 바로 공유(내보내기)하기
const appName = '노드모듈샘플 어플리케이션';

//모듈내 배열값 변수 내보내기
let serviceDomains = ['www.test.co.kr','test.com','test.co.kr'];


//plus함수 정의하기
const plus = (a, b) => a + b

//minus 함수 정의하기
function fnMinus(a, b){
    return a-b;
}

//HTML태그 제거 함수 정의하기
function fnRemoveTags(contents){
    return contents.replace(/<[^>]+>/g, '');
}

//텍스트 길이 기반 문자열 반환함수 정의
function textConverter(text,length) {
    let resultString = text.substring(0,length);
    if(text.length > length){
        resultString +="..";
    }
    return resultString;
}

//utility 모듈내 변수,상수,함수 내보내기
module.exports = {
    appName: appName,
    serviceDomains: serviceDomains,
    plus: plus,
    minus: fnMinus,
    removeTags:fnRemoveTags,
    textConverter:textConverter
}


먼저 module.exports ={객체} 방식으로 모듈내 여러 기능을 한방에 하나의 객체의 속성들로 정의하고
속성의 값으로 변수,함수등을 바인딩해 외부로 내보낼수 있습니다.


추가로 module.exports를 통해 하나의 기능만  노출할때는 아래와 같이 코딩도 가능합니다. 
const plus = (a, b) => a + b
module.exports = plus;

or 

module.exports.plus = plus;


B) exports.속성명 = 기능 방식으로 모듈내 기능 내보내기 

위 A)예시처럼  모듈내 기본 변수/상수/함수를 선 정의/구현하고 하단에서 module.exports = {} 객체의 속성과 값을 할당해 기능을 내보낼수도 있는지만
개별 변수,함수를 exports.동적속성명 =기능 또는 값 형태로 동일기능을 개별적으로 아래 예시와 같이 기능을 내보내기 할수도 있습니다. 

* utils1.js 와 utils2.js는 동일한 기능을 제공하는 유틸리티 개발자정의 모듈입니다.

-utils2.js 


//모듈내 변수나 상수값을 바로 공유(내보내기)하기
exports.appName = '노드모듈샘플 어플리케이션';

//모듈내 배열값 변수 내보내기
exports.serviceDomains = ['www.test.co.kr','test.com','test.co.kr'];


//plus함수 정의하기
exports.plus = (a, b) => a + b

//minus 함수 정의하기
exports.minus = function(a, b){
    return a-b;
}

//HTML태그 제거 함수 정의하기
exports.removeTags = function fnRemoveTags(contents){
    return contents.replace(/<[^>]+>/g, '');
}

//텍스트 길이 기반 문자열 반환함수 정의
exports.textConverter = function textConverter(text,length) {
    let resultString = text.substring(0,length);
    if(text.length > length){
        resultString +="..";
    }
    return resultString;
}



결론적으로 module.exports 와 exports.동적속성명 은 기본적으로  동일한 객체를 반환하게 됩니다.
exports.동적속성명으로 제공된 속성과 값들은 module.exports 의 결과와 동일하다는 것이며 모듈내 변수/상수/함수를 외부로 노출하고 싶으면
두가지중 한가지 방식을 이용하시면 됩니다. 주로 module.exports= {} 방식을 선호합니다.


2) 특정 모듈 사용하기(참조하기) 

위에서 정의한 utils1.js,utils2.js 모듈의 주요 기능을 다른 모듈에서 참조 사용하려면 노드에서는 require('참조모듈경로') 또는 require('설치모듈명') 등 require함수를 이용해 기능을 불러올수 있습니다.


ex) 다양한 모듈 참조 방식 예시 코드  

const utils = require('./utils1.js'); //개발자정의모듈 참조방식1
const {appName,serviceDomains,plus,minus,fnRemoveHtmlTag,textConverter} = require('./utils1.js');  //개발자정의모듈 참조방식2
const fs = require('fs');  //Node Framework 자체 제공 내장모듈 참조하기
const moment = require('moment'); //오픈소스저장소 다운로드 설치 패키지 참조하기 

모듈을 참조할때는 아래와 같이 2가지 방식을 통해 참조한 모듈의 값을 받아오고 사용할수 있습니다.
먼저 참조한 모듈을 단일 객체변수/상수로 받아와 변수/상수의 속성명을 호출하는 방식으로 사용하는 방법이 하

A) 모듈을 단일 객체변수/상수로 받아와 변수/상수의 속성명을 호출하는 방식
먼저 참조한 모듈을 단일 객체변수/상수로 받아와 변수/상수의 속성명을 호출하는 방식으로 사용하는 방법이 하

- index.js


const utils = require('./utils1.js');

console.log('앱이름 확인:',utils.appName);
console.log('도메인주소 목록 확인:',utils.serviceDomains);
console.log('plus함수 호출하기:',utils.plus(10,20));
console.log('minus 함수 호출하기:',utils.minus(50,20));
console.log('removeTags 함수 호출하기:',utils.removeTags("<div><h3>회사소개</h3> 안녕하세요.</div>"));
console.log('textConverter 함수 호출하기:',utils.textConverter("안녕하세요.",2));



B ) 모듈을 비구조화 할당 방식으로 필요한 속성만 정의해서 사용하는 방법

먼저 참조한 모듈을 객체 비구조화 할당방식으로 원하는 기능만 참조해서 사용하는 방법으로  상단의 단일 변수를 참조하는 방식과 기능은 동일하게 작동합니다.
차이점이라면 해당 모듈에서 100개의 기능을 노출하고 있어도 내가 원하는 속성만 비구조화 할당방식으로 바로 불러와 바로 사용한다는것만 차이가 있습니다. 

index.js

const {appName,serviceDomains,plus,minus,removeTags,textConverter} = require('./utils1.js');

console.log('앱이름 확인:',appName);
console.log('도메인주소 목록 확인:',serviceDomains);
console.log('plus함수 호출하기:',plus(10,20));
console.log('minus 함수 호출하기:',minus(50,20));
console.log('fnRemoveHtmlTag 함수 호출하기:',removeTags("<div><h3>회사소개</h3> 안녕하세요.</div>"));
console.log('textConverter 함수 호출하기:',textConverter("안녕하세요.",2));


노드 백엔드 모듈 기초 사용법을 알아보았습니다.
코드의 재사용을 위해 주로 모듈을 구현하며 Node Framework 자체 각종 내장모듈도 존재하지만 노드 개발자들은 서비스 기능 구현과 코드 재사용 위해 반드시 기본적인 개발자 정의 모듈 구현 및 그 사용법을 알고 있었야 합니다. 

참고로 index.js에서  참조하는 모듈을 utils2.js로 변경해 참조하고 동일 기능을 호출해도
동일하게 작동합니다.