변경 요약:

  • CommonJS 핵심 개념과 패턴을 구조화
  • 2026 기준 ESM 기본 원칙과 전환 팁 추가
  • TODO: 프로젝트별 Node.js 최소 버전 검증 필요

이 글에서 얻는 것:

  • exportsmodule.exports 차이 이해
  • CJS 모듈 분리 패턴 3가지 파악
  • ESM 전환 시 체크해야 할 규칙 정리

목차

1. exports 사용

exports는 어디에서나 접근 가능하고 속성 추가 가능

  • exports.속성에 함수 추가
    user.js
    --------
    exports.test1 = function(){
    return {id : 'hello', name : 'kimchanhee'};
    } 
    
  • exports.속성에 객체 추가
    user.js
    --------
    exports.test2 = {id : 'hello2', name : 'kimchanhee2'};
    
  • 다른 js에서 사용 , require() 메서드사용
    var user = require('./user'); // require() 메서드는 exports가 속성으로 할당
    

    참고: exports에 객체를 직접 할당하면 새로운 변수로 인식

    user.js
    --------
    exports = {
    test : {id : 'hello', name : 'kimchanhee'};
    }
    ----------------------------------------------------
    var user = require('./user'); = X 오류발생
    

2. module.exports 사용

  • module.exports에 객체 할당
user1.js
--------
var user = {
  test1 : function() {
    return {id : 'hello', name : 'kimchanhee'};
  },
  test2 : {id : 'hello2', name : 'kimchanhee2'}
}

module.exports = user;
-----------------------------------------------------
var user = require('./user1'); //module.exports에 할당한 객체가 반환
console.log(user.test2.id); // "hello2"
  • module.exports에 함수 할당
user1.js
--------
module.exports = function() {
  return {id : 'hello', name : 'kimchanhee'};
}
-----------------------------------------------------
var user = require('./user1'); // module.exports에 할당한 익명함수가 반환
console.log( user().name ); // "kimchanhee"

module.exports에 익명함수가 반환된다. ()소괄호를 붙여 함수 실행


3. exports VS module.exports

exports 전역변수와 module.exports 를 함께 사용하면 module.exports가 우선 적용
※ module.exports 사용 권장


4. 모듈 분리할때 전형적인 코드 방법

  1. 함수를 할당하는 경우
  2. 인스턴스 객체를 할당하는 경우
  3. 프로토타입 객체를 할당하는 경우

1) 함수를 할당 하는 경우

 user2.js
 --------
 module.exports = function() {
   return {id : 'hello', name : 'kimchanhee'};
 }
 -----------------------------------------------------
 var user = require('./user2'); //
 console.log( user().name ); // "kimchanhee"

2번과 동일

2) 인스턴스 객체를 할당하는 경우

user2.js
--------
// 생성자 함수
function User(id, name) {
	this.id = id;
	this.name = name;
}
//프토토타입 속성추가
User.prototype.print = function() {
	console.log('id : %s, name : %s', this.id, this.name);
}

module.exports = new User('test', '김찬희');
---------------------------------------------
var user = require('./user2'); // new User('test', '김찬희');

user.print(); // "id: test, name : 김찬희"
console.log(user.id); // "test"

var user에는 new User()로 만든 인스턴스 객체가 반환된다.

3) 프로토타입 객체를 할당하는 경우

user2.js
--------
// 생성자 함수
function User(id, name) {
	this.id = id;
	this.name = name;
}
//프토토타입 속성추가
User.prototype.print = function() {
	console.log('id : %s, name : %s', this.id, this.name);
}

exports.User = User;
--------------------
var Test = require('./user2').User; // exports.User 참조, 즉 User 객체 참조
var user = new Test('test', '김찬희'); // new 연산자로 인스턴스객체 생성

user.print(); // "id: test, name : 김찬희"

exports 객체에 속성을 추가 한 후 프로토타입 객체를 정의 하고, require() 메서드로 반환되는 객체는 exports 이므로 그 안에 추가한 User객체를 참조 한 후 new 연산자로 인스턴스 객체를 만들 수 있다.


5. 현재(2026) 기준: ESM 기본, CJS는 호환

Node.js 최신 LTS 기준에서는 ESM이 기본이고, CJS는 레거시 호환으로 유지됩니다.

ESM 기본 설정 예시

// package.json
{
  "type": "module"
}
// math.js (ESM)
export const add = (a, b) => a + b;
export default function multiply(a, b) {
  return a * b;
}

// main.js (ESM)
import multiply, { add } from './math.js';

CJS/ESM 공존 팁

  • CJS 파일은 .cjs, ESM 파일은 .mjs로 분리하면 명확합니다.
  • CJS에서 ESM을 불러올 때는 import()(동적 import) 사용이 안전합니다.
  • TODO: 빌드 도구(예: Babel, TS)와 배포 환경에 맞춘 설정 검증 필요
chanhee.kim's profile image

chanhee.kim

2017-11-16 18:38

Read more posts by this author