node.js의 모듈 시스템은 코드를 작성하고 관리하기 쉽게 하기 위해 자바스크립트 파일을 여러 개의 작은 단위로 분리할 수 있는 기능을 제공한다.
이렇게 분리된 파일을 모듈이라고 부르며 각 모듈은 다른 모듈에서 사용할 수 있는 함수, 객체. 변수 등을 정의할 수 있다.
모듈을 사용하는 방법은 3가지가 있다.
내장 모듈 사용하기
node.js는 기본적으로 다양한 내장 모듈을 제공한다. 내장 모듈을 사용하려면 require 함수를 사용하여 모듈을 불러온다.
const fs = require('fs');
외부 모듈 사용하기
NPM(node package manager)을 사용하여 다른 개발자가 작성한 외부 모듈을 설치하고 사용한다.
npm install axios
node.js에서 모듈 시스템은 주로 CommonJS와 ES Modules 두 가지 방식을 사용한다.
const axios = require('axios');
사용자 정의 모듈
사용자 정의 모듈을 사용하려면 코드를 작성하고 ‘module.exports’ 객체에 내보낼 객체를 할당한다.
function sayHello(name) {
console.log(`Hello, ${name}!`);
}
module.exports = {
sayHello: sayHello
};
사용자 정의 모듈을 사용하려면 파일을 require함수를 사용해 불러온다.
const myModule = require('./myModule.js');
myModule.sayHello('John');
node.js에서 주요 모듈 시스템은 두 가지 방법이 있다.
CommonJS
CommonJS는 node.js에서 초기부터 사용하던 모듈 시스템으로 require() 함수와 module.exports 객체를 사용해 모듈을 불러오고 내보내는 방식을 제공한다.
function sayHello(name) {
console.log(`Hello, ${name}!`);
}
module.exports = {
sayHello: sayHello
};
const myModule = require('./myModule.js');
myModule.sayHello('John');
CommonJS는 동기적인 방식으로 모듈을 불러오기 때문에 서버 사이드 환경에서 주로 사용된다.
ES Modules
ES Modules는 ECMAScript 2015 (ES6)부터 도입된 모듈 시스템으로 import와 export 키워드를 사용하여 모듈을 불러오고 내보내는 방식을 제공한다.
export function myFunction() {
// 함수 구현
}
import { myFunction } from './myModule';
myFunction();
ES Moudules는 비동기적인 방식으로 모듈을 불러오며 브라우저와 서버 모두에서 사용할 수 있다.
CommonJS와 ES Modules의 주요 차이점은 다음과 같다.
문법
CommonJS는 require() 함수와 module.exports 객체를 사용한다 ES Modules는 import와 export 키워드를 사용한다.
동기 vs 비동기
CommonJS는 동기적인 방식으로 모듈을 불러온다.
ES Modules는 비동기적인 방식으로 모듈을 불러온다.
환경
CommonJS는 서버 사이드 환경에서 주로 사용된다.
ES Modules는 브라우저와 서버 모두 사용할 수 있다.
정적 vs 동적
CommonJS는 런타임에 동적으로 모듈을 처리한다.
ES Modules는 정적으로 모듈을 분석하여 최적화가 가능하다.
이로 인해 ES Modules가 트리 쉐이킹 같은 최적화 기법을 사용할 수 있는 장점이 있다.
모듈 시스템의 정적과 동적 방식이란?
동적(commonJS)
commonJS는 런타임에 동적으로 모듈을 처리한다. 프로그램이 실행되는 도중에 ‘require’ 함수를 통해서 모듈을 불러오고 처리한다. 이러한 동적 처리 방식은 모듈 로딩 순서를 명확하게 알 수 있으며 조건부로 모듈을 불러올 수 있다. 하지만 동적 처리 방식은 런타임 이전에 모듈 간의 종속성을 파악하기 어렵고 트리 쉐이킹과 같은 최적화 기법을 적용할기 어렵다
정적(ES Modules)
ES Modules는 정적을 모듈을 분석하여 처리한다. 프로그램이 실행되기 전에 빌드 과정에서 ‘import’, ‘export’ 구문을 통해서 모듈 간의 종속성을 분석하고 처리한다. 이러한 처리 방식은 런타임 이전에 모듈 구조와 종석성을 파악할 수 있어 최적화에 유리한다. 정적 처리 덕분에 트리 쉐이킹과 같은 최적화 기법을 적용할 수 있다. 하지만 정적 처리 방식에서는 조건부로 모듈을 불러오거나 실행 중 모듈을 변경하기 어렵다.
트리 쉐이킹
사용하지 않는 코드를 제거하여 번들의 크기를 줄이는 최적화 기법
예) 애플리케이션
// utils.js
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
export function unusedFunction(x) {
return x * 2;
}
// app.js
import { square, cube } from './utils.js';
console.log(square(2)); // 4
console.log(cube(2)); // 8
애플리케이션은 ‘square’와 ‘cube’ 함수만 사용하고 있다.
‘unusedFunction’은 사용되지 않는다.
그럼에도 불구하고 번들링 과정에서 이 함수가 번들에 포함되어 불필요한 코드가 로드된다.
트리 쉐이킹을 사용하면 번들링 과정에서 사용하지 않는 코드를 제거하여 번들 크기를 줄인다.
모듈 시스템의 동기식 방식과 비동기식 방식이란?
두 방식의 차이는 모듈 로딩 및 실행 과정에서 발생한다.
동기식 방식
동기식 방식은 모듈이 로드되고 실행되는 과정이 순차적으로 이루어진다.
즉 모듈이 로드되고 완료되기 전까지 다음 코드 실행이 대기 상태에 있다. 이로 인해 코드 실행 순서를 명확하게 알 수 있지만 모듈 로딩 시간이 길어질 경우 천체 코드 실행이 지연될 수 있다.
서버 환경에서는 모듈 로딩 시간이 상대적으로 빠르기 때문에 동기식 방식이 큰 문제가 되지 않는다.
비동기식 방식
비동기식 방식은 모듈 로딩 과정이 병렬로 실행된다. 모듈 로드되는 동안 다른 코드 실행이 중단되지 않고 계속 진행된다. 이로 인해 코드 실행이 지연되지 않지만 모듈 간의 종속성을 관리해야 할 경우 복잡성이 증가한다.
ES Modules는 비동기식 방식을 사용하고 브라우저 환경에서 성능 향상을 위해 도입되었다.
브라우저 환경은 네트워크 상화에 따라 모듈 로딩 시간이 길어질 수 있기 때문에 비동기식 방식이 동기식 방식보다 더 효율적이다.
그렇다면 우리는 어떤 모듈 시스템을 선택해야 할까?
몇 가지 사항을 고려해 목적과 환경에 따라 선택하자
환경
서버 사이드(node.js) 전용 프로젝트의 경우 commonJS를 선택하는 것이 더 간단하고 일반적이다. 대부분의 서드파티 라이브러리가 commonJS로 작성되어 있기 때문이다.
브라우저와 서버 사이드에서 모두 작동해야 하는 프로젝트라면 ES Modules를 사용하는 것이 좋다. 최신 웹 브라우저는 ES Modules를 지원하며 node.js에서도 안정화되어 사용하기 좋다.
최신 자바스크립트 기능 사용
최신 자바스크립트 기능 및 구문을 사용하면 ES Modules를 선택하는 것이 좋다. ES Modules는 최신 ECMAScript 표준을 따르기 때문에 최신 기능과 호환성이 좋다.
비동기 로딩과 성능
모듈의 비동기 로딩과 성능 최적화가 중요한 경우 ES Modules를 선택하는 것이 좋다.
ES Modules는 비동기식 로딩 방식을 사용하여 브라우저 환경에서 성능을 최적화할 수 있다.
프로젝트의 규모와 유지 보수성
프로젝트가 커지고 복잡해질수록 ES Modules를 사용하여 모듈 간의 종속성을 명확하게 관리하는 게 코드의 유지 보수성이 향상된다.
서드파티 라이브러리 호환성
프로젝트에서 다양한 서드파티 라이브러리를 사용해야 하는 경우 해당 라이브러리들이 어떤 모듈 시스템을 지원하는지 확인하고 호환되는 모듈 시스템을 선택하는 것이 좋다.
최신 웹 애플리케이션을 개발한다면 ES Modules를 사용하는 것이 좋은 선택일 수 있다.
전통적인 node.js 프로젝트를 개발한다면 commonJS가 더 적합할 수 있다.
'과거공부모음' 카테고리의 다른 글
실행 컨텍스트와 스코프 (0) | 2023.04.20 |
---|---|
버퍼(buffer)와 스트림(stream) (0) | 2023.04.20 |
개발 방법론 (0) | 2023.04.19 |
웹 보안 (0) | 2023.04.19 |
자료구조 알고리즘 (0) | 2023.04.18 |