728x90
반응형

모듈 시스템은 코드를 구조화하고 재사용할 수 있게 해주는 방식으로, 큰 애플리케이션을 작은 단위로 분리하여 관리할 수 있도록 도와줍니다. 모듈 시스템은 코드의 의존성을 명확하게 정의하며, 모듈 간의 상호작용을 효율적으로 처리할 수 있습니다.

※ Java 라이브러리와 Javscript 모듈의 차이

  • Java의 라이브러리컴파일 시점에 주로 의존성을 관리하고, JAR 파일로 배포되는 패키지입니다.(정적)
  • JavaScript의 모듈 시스템은 파일 단위의 모듈을 관리하며, 주로 런타임에 모듈을 로딩하는 방식으로 동작합니다.(동적)
  • Java 9의 모듈 시스템은 컴파일 시점뿐 아니라 런타임 시점에서도 모듈 간의 의존성을 관리하고 검증하는 기능을 강화했습니다. 하지만 이는 JavaScript의 동적 모듈 로딩과 같은 방식은 아닙니다

1. 모듈 시스템의 개념

모듈 시스템은 애플리케이션 내에서 코드를 여러 모듈로 나누고, 각 모듈이 필요한 기능을 내보내고(import/export), 다른 모듈에서 이를 불러와 사용하는 방식을 의미합니다. 모듈 시스템이 없다면, 모든 코드가 하나의 파일이나 전역 스코프에서 작성되어 코드 충돌유지보수의 어려움이 발생할 수 있습니다.

모듈 시스템은 다음과 같은 기능을 제공합니다:

  • 코드 분리 및 재사용성: 모듈을 독립된 단위로 나누어, 코드를 재사용하고 유지보수를 쉽게 할 수 있습니다.
  • 의존성 관리: 모듈 간 의존성을 명확하게 관리하여, 프로젝트의 복잡성을 줄입니다.
  • 캡슐화: 모듈 내부의 코드를 외부에서 접근하지 못하도록 하여, 불필요한 데이터 노출을 막습니다.

JavaScript에서는 주로 CommonJSECMAScript Modules (ESM) 두 가지 모듈 시스템을 사용합니다. 이 두 시스템은 코드의 가져오기(import) 및 내보내기(export) 방식을 정의하며, 각각의 특징에 따라 컴파일 및 런타임에서 다르게 동작합니다.


2. CommonJS (CJS)

CommonJSNode.js에서 사용되는 기본 모듈 시스템으로, 서버 사이드 자바스크립트 환경에서 널리 사용됩니다. CommonJS는 모듈을 동기적으로 로딩하고, 런타임 시 require() 함수를 사용하여 모듈을 불러옵니다.

주요 특징:

  • 모듈 가져오기: require() 함수를 통해 다른 모듈을 가져옵니다.
const moduleA = require('./moduleA');
  • 모듈 내보내기: module.exports로 모듈을 내보냅니다.
module.exports = {
    myFunction: () => { /* ... */ }
};
  • 동기적 로딩: CommonJS는 모듈을 동기적으로 로딩하며, 서버 환경에서 이러한 동기적 특성은 성능 문제를 일으키지 않지만, 브라우저 환경에서는 비효율적일 수 있습니다.

장점:

  • Node.js 기본 모듈 시스템: Node.js 환경에서의 기본 설정으로, 대부분의 Node.js 프로젝트와 라이브러리에서 널리 사용됩니다.
  • 간단한 구조: require()module.exports의 단순한 문법으로 모듈을 쉽게 관리할 수 있습니다.

단점:

  • 브라우저에서의 사용 제한: CommonJS는 브라우저에서 바로 사용할 수 없습니다. 브라우저는 동기적 로딩이 불가능하기 때문에, 번들러(Webpack, Browserify)를 사용해야 합니다.
  • 트리 셰이킹 지원 부족: CommonJS는 트리 셰이킹을 지원하지 않으므로, 불필요한 코드까지 번들링될 수 있습니다.

3. ECMAScript Modules (ESM)

ECMAScript Modules (ESM)는 JavaScript의 표준 모듈 시스템으로, 브라우저Node.js에서 모두 사용됩니다. ESM은 비동기적으로 모듈을 로딩하며, 최신 브라우저 환경과 Node.js 최신 버전에서 기본적으로 지원됩니다.

주요 특징:

  • 모듈 가져오기: import 문을 사용해 모듈을 가져옵니다.
import { myFunction } from './moduleA';
  • 모듈 내보내기: export 키워드로 모듈을 내보냅니다.
export const myFunction = () => { /* ... */ };
  • 비동기적 로딩: ESM은 모듈을 비동기적으로 로딩하여 성능을 최적화합니다. 이는 특히 대규모 웹 애플리케이션에서 유리합니다.

장점:

  • 브라우저와 Node.js 모두 지원: ESM은 브라우저Node.js 환경에서 모두 사용할 수 있습니다.
  • 트리 셰이킹 지원: 사용하지 않는 코드를 제거하여 번들 크기를 줄이고 성능을 향상시킬 수 있습니다.

단점:

  • Node.js 설정 필요: Node.js에서 ESM을 사용하려면 package.json 파일에 "type": "module"을 명시해야 합니다.
  • 기존 CommonJS 코드와의 호환성 문제: CommonJS와 ESM은 서로 호환되지 않기 때문에, 두 시스템을 함께 사용할 때 호환성 문제가 발생할 수 있습니다.

4. 컴파일러와 런타임에서의 동작

CommonJS (CJS):

  • 컴파일: CommonJS는 컴파일 단계 없이 런타임에 require()로 모듈을 가져옵니다.
  • 런타임: 런타임에 모듈을 동기적으로 로딩하며, 한 번 로드된 모듈은 캐시되어 이후 요청 시 캐시된 버전을 사용합니다.

ECMAScript Modules (ESM):

  • 컴파일: ESM은 정적 분석을 통해 모듈 간의 의존성을 컴파일 시점에 분석하며, 트리 셰이킹을 통해 불필요한 코드를 제거할 수 있습니다.
  • 런타임: ESM은 비동기적으로 모듈을 로딩하여, 필요한 시점에만 모듈을 가져옵니다.

5. CommonJS와 ESM의 비교

CommonJS (CJS) ECMAScript Modules (ESM)
모듈 로딩 방식 동기적 로딩 (require) 비동기적 로딩 (import/export)
사용 환경 주로 Node.js 브라우저Node.js 모두 지원
트리 셰이킹 지원하지 않음 트리 셰이킹 지원
컴파일 컴파일 단계 없음, 런타임에서 동작 컴파일 시 의존성 분석 및 최적화 가능
모듈 캐싱 모듈은 한 번 로드된 후 캐시 모듈은 필요할 때 로드됨

결론

JavaScript의 모듈 시스템은 코드의 구조화를 도와 유지보수성을 높이고, 의존성 관리를 명확하게 할 수 있게 해줍니다. CommonJSNode.js 환경에서 기본적으로 사용되며, 서버 사이드 애플리케이션에서 널리 쓰입니다. 반면, ECMAScript Modules (ESM)브라우저Node.js 모두에서 사용할 수 있는 최신 표준으로, 비동기적 로딩과 트리 셰이킹 기능을 지원해 성능과 최적화를 제공합니다.

어떤 모듈 시스템을 사용할지는 프로젝트의 환경필요한 기능에 따라 결정되어야 하며, 최신 웹 애플리케이션이나 브라우저 환경에서는 ESM이 권장됩니다.

반응형