JavaScript의 모듈 시스템: require vs import

By | 9월 7, 2025
JavaScript의 모듈 시스템: require vs import

자바스크립트 모듈 시스템: require vs import

자바스크립트는 본래 단순한 웹 스크립팅 언어로 시작했습니다. 그러나 애플리케이션의 규모가 점차 커지면서 코드의 재사용성을 높이고, 의존성을 관리하며, 변수명 충돌을 방지할 수 있는 체계적인 모듈 시스템의 필요성이 커졌습니다. 이러한 배경 속에서 CommonJS의 requireECMAScript Modules(ESM)의 import라는 두 가지 주요 모듈 시스템이 등장했습니다.


등장 배경과 특징

require (CommonJS)

require는 주로 2009년경 Node.js가 등장하며 서버 측 자바스크립트 개발의 표준으로 자리 잡았습니다. Node.js는 파일 시스템에 즉시 접근할 수 있기 때문에 모듈을 동기적으로 불러오는 require 방식이 매우 적합했습니다. 이 방식은 require 호출이 완료될 때까지 다음 코드가 실행되지 않게 하여, 서버 환경에서 예측 가능한 코드 흐름을 보장합니다.

import (ES Modules)

importECMAScript 2015(ES6) 표준의 일부로 공식화된 자바스크립트 언어 자체의 모듈 시스템입니다. 기존의 비공식 모듈 시스템이 가진 한계를 극복하고 언어 차원의 통일된 모듈 기능을 제공하기 위해 설계되었습니다. import는 웹 브라우저 환경을 고려하여 모듈을 비동기적으로 불러올 수 있도록 설계되었습니다. 이 비동기 특성 덕분에 네트워크를 통해 모듈을 가져와야 하는 브라우저에 최적화되어 있습니다. 또한, import정적 분석이 가능해 번들링 도구와 같은 개발 도구들이 코드 의존성을 효율적으로 파악하고, 사용되지 않는 코드를 제거하는 트리 쉐이킹(Tree Shaking) 같은 최적화 기술을 적용하는 데 매우 유리합니다.


모듈 사용 방법

require (CommonJS)

CommonJS에서는 module.exports를 사용하여 모듈의 기능을 외부에 공개하고, require() 함수로 모듈을 가져옵니다. 명시적인 기본(default) 내보내기나 이름(named) 내보내기 개념은 없으며, module.exports에 할당된 값이 모듈 전체의 단일 내보내기가 됩니다.

1. 모듈 내보내기 (module.exportsexports)

  • module.exports 객체 할당 방식: 여러 함수나 값을 하나의 객체로 묶어 내보낼 때 사용합니다. 이 방식은 module.exports의 기존 값을 완전히 덮어씁니다.
    // math.js
    export const add = (a, b) => a + b;
    export const subtract = (a, b) => a - b;
  • exports 객체 속성 추가 방식: exportsmodule.exports를 참조하는 변수입니다. 여러 개의 속성을 개별적으로 내보낼 때 편리합니다.
    // calculator.js
    const multiply = (a, b) => a * b;
    export default multiply;

2. 모듈 가져오기 (require())

require() 함수는 module.exports로 내보낸 객체나 값을 반환합니다.

// app.js

const math = require('./math');
console.log(math.add(5, 3)); // 8

const { multiply, divide } = require('./calculator');
console.log(multiply(4, 5)); // 20

import (ES Modules)

ES Modules에서는 exportimport 키워드를 사용합니다. 기본 내보내기(default export)와 이름 있는 내보내기(named export)를 명확하게 구분하는 것이 특징입니다.

1. 모듈 내보내기 (export)

  • Named Exports (이름 있는 내보내기): 여러 함수, 변수, 클래스 등을 각각의 이름으로 내보냅니다. 가져올 때도 동일한 이름을 사용해야 합니다
// math.js 
export const add = (a, b) => a + b; 
export const subtract = (a, b) => a - b;
  • Default Export (기본 내보내기): 모듈당 단 하나만 내보낼 수 있는 방식입니다. 모듈을 가져올 때 원하는 이름으로 자유롭게 지정할 수 있습니다.
// calculator.js 
const multiply = (a, b) => a * b; export default multiply;

2. 모듈 가져오기 (import)

  • Named Imports (이름으로 가져오기): export된 특정 요소를 선택적으로 가져옵니다. as 키워드를 사용해 별칭을 부여할 수도 있습니다.
// app.js 
import { add } from './math.js'; 
console.log(add(5, 3)); // 8 
import { subtract as minus } from './math.js'; 
console.log(minus(10, 4));

// 모든 named export를 하나의 객체로 가져올 수도 있습니다
import * as MathFunctions from './math.js'; 
console.log(MathFunctions.add(2, 2)); // 4
  • Default Import (기본 가져오기): default export된 모듈을 가져옵니다. 중괄호 {} 없이 원하는 이름을 지정합니다.
// app.js 
import calculate from './calculator.js'; 
console.log(calculate(4, 5)); // 20

Node.js에서의 package.json 설정

Node.js 환경에서 두 모듈 시스템을 명시적으로 사용하려면 package.json 파일의 type 필드를 설정해야 합니다.

CommonJS 프로젝트

기본적으로 package.jsontype 필드가 없거나 "type": "commonjs"로 설정되면 Node.js는 해당 프로젝트를 CommonJS 모듈로 간주합니다.

// package.json (CommonJS 기본)
{
  "name": "my-commonjs-app",
  "type": "commonjs", // 이 필드가 없어도 동일하게 작동
  "main": "index.js"
}

ES Modules 프로젝트

Node.js에서 ES Modules를 사용하려면 package.json"type": "module"을 추가해야 합니다. 이 설정은 해당 패키지 내의 .js 파일을 ES Modules로 해석하게 합니다.

JSON

// package.json (ES Modules 설정)
{
  "name": "my-esm-app",
  "type": "module", // ES Modules 사용을 명시
  "main": "index.js"
}

확장자 규칙:

  • .js: package.jsontype 설정에 따라 CommonJS 또는 ES Modules로 동작합니다.
  • .mjs: type 설정에 관계없이 항상 ES Modules로 해석됩니다.
  • .cjs: type 설정에 관계없이 항상 CommonJS로 해석됩니다.

현재 자바스크립트 생태계는 ES Modules를 표준으로 채택하고 있으며, 대부분의 환경에서 ES Modules로의 전환이 이루어지고 있습니다. 하지만 기존 프로젝트나 특정 환경에서는 여전히 CommonJS가 사용될 수 있어 두 시스템의 차이를 이해하는 것이 중요합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다