변경 요약:
- CommonJS 핵심 개념과 패턴을 구조화
- 2026 기준 ESM 기본 원칙과 전환 팁 추가
- TODO: 프로젝트별 Node.js 최소 버전 검증 필요
이 글에서 얻는 것:
exports와module.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) 함수를 할당 하는 경우
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)와 배포 환경에 맞춘 설정 검증 필요