모듈

HS K·2022년 11월 9일

모듈

프로그램을 구성하는 구성 요소로, 관련된 데이터와 함수를 하나로 묶은 단위를 의미한다. 쉽게말하면 파일 하나라고 보면 된다.

※ 보통 하나의 소스 파일에 모든 함수를 작성하지 않고, 함수의 기능별로 따로 모듈을 구성한다. 또한, 여러 모듈이 조합되어 하나의 소프트웨어를 이루게 된다.
즉, 프로그램을 만들 때 코드를 잘 모듈화해서 만들게 되면 유지보수하기 쉬운 구조로 시스템을 만들 수 있다.

P.S 결국에는 모듈화가 잘 된 코드는 재사용성확장성을 높여 새로운 기능을 개발하거나 유지보수 할 때, 전체적인 비용을 감소시키고 개발팀의 생산성을 증대시킬 수 있다. 그만큼 모듈화는 지속 가능한 소프트웨어 개발에 있어서 중요한 부분이다.

참고
javascript는 언어차원에서 모듈을 위한 명시적인 키워드나 패키징 정책을 지원하지 않았기 때문에 모듈화와는 거리가 먼 언어였지만, CommonJS라는 워킹 그룹이 JavaScript를 브라우저에서뿐만 아니라, 서버사이드 애플리케이션이나 데스크톱 애플리케이션에서도 사용하기 위해 가장 의미있는 결과를 만들어 냈다.
이 그룹은 JavaScript를 범용적으로 사용하기 위해 필요한 '명세(Specification)'를 만들었고, Node.js 모듈 시스템도 CommonJS의 Module specification을 따르고 있다.


모듈의 핵심 기능

  1. 엄격 모드
    모듈은 항상 엄격 모드(use strict)로 실행된다. 선언되지 않은 변수에 값을 할당하는 등의 코드는 에러를 발생시킨다.
<script type="module">
  a = 5; // 에러
</script>
  1. 모듈 레벨 스코프
    모듈은 자신만의 스코프가 있다. 따라서 모듈 내부에서 정의한 변수나 함수는 다른 스크립트에서 접근할 수 없고, 모듈 내부에서 정의한 변수나 함수는 export & import로만 접근할 수 있다.
  1. 여러 곳에 사용되더라도 최초 호출 시 단 한 번만 사용
    모듈은 단 한 번만 실행되고, 실행된 모듈은 필요한 곳에 공유된다.
  1. import.meta 객체를 통하여 현재 모듈에 대한 정보 제공
    브라우저 환경에서 스크립트의 URL 정보를 확인할 수 있다.

CommonJS의 모듈 명세는 모듈을 어떻게 정의하고, 어떻게 사용할 것 인지에 대한 것으로 모듈화에 필요한 것은 크게 세 가지이다.

스크립트와 모듈간의 차이는 뭘까?

모듈은 import/export 구문을 사용하여 다른 모듈이나 파일에서 재사용할 수 있는 코드를 정의하는 반면, 스크립트는 일련의 코드 명령어를 실행하는 파일일 뿐이다.

모듈

export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

스크립트

<!DOCTYPE html>
<html>
  <head>
    <title>Script Example</title>
  </head>
  <body>
    <h1>Script Example</h1>
    <button id="myButton">Click me!</button>
    <script>
      const button = document.getElementById('myButton');
      button.addEventListener('click', () => {
        alert('Button clicked!');
      });
    </script>
  </body>
</html>

첫 번째

모든 모듈은 자신만의 독립적인 실행 영역이 있어야 한다.
그 이유는 코드의 재사용성을 높이고 가독성을 높이기 위함이다. 모듈을 사용하면, 해당 모듈이 제공하는 기능을 다른 모듈에서 재사용할 수 있으며, 이를 통해 코드의 중복을 피하고 유지보수성을 높일 수 있기 때문이다.

이 말은 전역변수(Global variable)와 지역변수(Local variable)를 분리하는 것을 의미한다.
그 이유는 전역변수는 다양한 모듈에서 동일한 변수를 참조할 때 이름 충돌이 발생할 수 있으며, 이로 인해 예기치 않은 동작이 발생할 수 있기 때문이다.

서버 사이드 JavaScript의 경우에는 파일마다 독립적인 파일 스코프가 있기 때문에 파일 하나에 모듈 하나를 작성하는 방법으로 독립적인 실행 영역을 만든다.

  • 전역변수 : 전역에서 선언된 변수이며 어디에든 참조할 수 있다.
  • 지역변수 : 지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.
  • 스코프 : 식별자 접근 규칙에 따른 유효 범위. 범위는 중괄호(블록) 또는 함수에 의해 나눠진다.
    ※ 스코프 주요규칙은 여기에서 참고하자.

두 번째

모듈을 외부에서 사용할 수 있도록 공개하는 것인데, Node.js (CommonJS의 모듈 명세를 따르는)에서는 exports라는 전역 객체를 이용해서 정의한다.

마지막

모듈을 사용하는 영역에서는 require() 함수를 이용해서 모듈을 불러온다.

Custom module 만들기

1. exports 객체를 사용하여 만드는 방법

모듈을 파일로 작성하고 외부에 공개할 대상을 exports 객체의 프로퍼티 또는 메소드를 정의하는 방법

// calculator.js
const initialNumber = 0

exports.add = (x, y) => initialNumber + x + y; // export 객체에 add method 정의
exports.substract = (x, y) => initialNumber + x - y; // export 객체에 substract method 정의

calculator.js는 독립적인 파일 스코프를 갖는 모듈이다.

calculator 모듈에 add와 substract를 exports 객체의 메소드로 정의하였다.
변수 initialNumber는 calculator 모듈에서만 유효한 private 변수가 되고, add와 substract 메소드는 외부에 공개되어 필요한 곳에서 사용할 수 있다.

이제 add와 subtract 함수가 필요한 곳에서 require() 함수를 사용하여 임의의 이름으로 circle 모듈을 import 할 수 있다.

// main.js

const calculator = require("./calculator.js");

console.log(`1 + 5 =  ${calculator.add(1, 5)}`);
console.log(`1 - 5 =  ${calculator.subtract(1, 5)}`);

이때 require 함수 호출 결과 calculator 모듈은 객체 형태로 반환되어 calculator 변수에 담기게 된다.
따라서 calculator.add, calculator.sub과 같은 형식으로 공개된 calculator 모듈을 참조한다.

이제 아래 명령어를 사용해서 main.js 코드를 실행해보면 정상적으로 분리된 모듈을 참조해서 사용할 수 있음을 알 수 있다.

$ node main

1 + 5 = 6
1 - 5 = -4

2. module.exports를 사용하여 만드는 방법

앞에서 살펴본 exports 객체는 여러 개의 속성과 메소드를 정의할 수 있었지만, module.exports에는 하나의 객체만 할당할 수 있다.

※ 두 차이는 module에 한번에 담냐, 아니면 한줄씩 export하냐 라고 생각하면 된다.

// calculator.js
const initialNumber = 0

function add(a, b) {
  return a + b;
}

function substract(a, b) {
  return a - b;
}

module.exports = {
  add,
  substract
}

// main.js

const calculator = require("./calculator.js");

console.log(`1 + 5 = ${calculator.add(1, 5)}`);
console.log(`1 - 5 = ${calculator.substract(1, 5)}`);

위의 코드는 require 함수를 통해 calculator 모듈을 import하여 calculator 변수에 할당했다.
또는 아래와 같이 구조분해 할당을 이용해서 import 할 수도 있다.

// main.js
const {add, substract} = require("./calculator.js");

console.log(`1 + 5 = ${add(1, 5)}`);
console.log(`1 - 5 = ${substract(1, 5)}`);
profile
주의사항 : 최대한 정확하게 작성하려고 하지만, 틀릴내용이 있을 수도 있으니 유의!

0개의 댓글