📘 17.3.3 ES6 모듈과의 차이점 - 두 개의 다른 언어처럼
코드를 나누어 담는 방법에도 각각의 색깔이 있습니다. 지금까지 우리가 배워온 CommonJS의 따뜻한 품 안에서 module.exports
와 require
라는 친숙한 단어들과 함께해왔지만, 자바스크립트 세상에는 또 다른 길이 있어요. ES6 모듈이라는 새로운 방식이 우리를 기다리고 있습니다.
마치 같은 하늘을 바라보지만 서로 다른 언어로 이야기하는 두 사람처럼, 이 두 방식은 같은 목적을 가지고 있으면서도 각자만의 독특한 표현 방식을 가지고 있어요. 이번 시간에는 이 아름다운 차이점들을 함께 살펴보겠습니다.
🧠 먼저 용어를 알아볼까요?
새로운 세상을 탐험하기 전에, 우리가 함께 사용할 단어들의 의미를 차근차근 알아보겠습니다.
용어 | 의미 |
---|---|
CommonJS | Node.js에서 주로 사용하는 모듈 시스템으로, 우리가 지금까지 함께 걸어온 익숙한 길입니다. |
ES6 모듈 | 브라우저에서 주로 사용하는 새로운 표준 자바스크립트 모듈 시스템입니다. |
미리 계획하는 가져오기 | 코드를 실행하기 전에 미리 분석되는 가져오기 방식을 말합니다. |
즉석에서 가져오기 | 코드가 실행되는 중에 필요할 때 처리되는 가져오기 방식을 의미합니다. |
✨ 두 방식의 핵심 특징
CommonJS와 ES6 모듈은 마치 서로 다른 계절의 풍경과 같습니다. 둘 다 코드를 나누고 공유한다는 같은 꿈을 꾸고 있지만, 그 꿈을 이루는 방법과 표현이 조금씩 다른 거예요.
CommonJS는 오래전부터 Node.js라는 서버 세상에서 사랑받아온 전통적인 방식입니다. 우리가 일상에서 자연스럽게 사용하는 말처럼, 간단하고 친근해요. 필요할 때마다 즉석에서 모듈을 불러올 수 있는 자유로움이 이 방식의 매력입니다.
반면 ES6 모듈은 브라우저에서 태어난 현대적인 방식입니다. 모든 것을 미리 계획하고 준비하는 꼼꼼함이 특징이에요. 조금 더 신중하게 접근해야 하지만, 그만큼 더 안전하고 효율적으로 움직입니다.
비유로 이해하기: 두 개의 다른 도서관
이 두 방식을 더 가까이에서 이해하기 위해, '두 개의 다른 도서관' 이야기를 함께 나누어볼까요?
CommonJS 도서관은 우리 동네에 있는 정겨운 도서관이에요. 필요한 책이 있으면 언제든 도서관에 가서 "과학책 하나 부탁드려요"라고 말하면 사서님이 바로 찾아주세요. 매우 편안하고 친근하지만, 때로는 책을 찾는 데 시간이 조금 걸릴 수도 있어요.
ES6 모듈 도서관은 최신식 자동화 도서관 같아요. 필요한 책을 미리 목록에 정확히 적어서 제출해야 해요. "수학책 1권, 과학책 2권, 동화책 3권"처럼 말이죠. 그러면 모든 준비가 끝난 후에 한꺼번에 깔끔하게 받을 수 있습니다. 조금 더 계획적이어야 하지만, 실제로 사용할 때는 매우 빠르고 효율적이에요.
두 방법 모두 저마다의 아름다움이 있어요. 첫 번째 방법은 자유롭고 유연하고, 두 번째 방법은 체계적이고 빨라요. 상황에 따라 어떤 방법이 더 어울릴지 선택할 수 있답니다.
🎯 두 방식을 배우는 이유
그렇다면 우리는 왜 두 가지 방식을 모두 알아두어야 할까요? 몇 가지 소중한 이유들이 있답니다.
먼저 각 환경에 맞는 선택을 할 수 있어요. 서버에서 작업할 때는 CommonJS가 더 편안하고, 웹 브라우저에서 작업할 때는 ES6 모듈이 더 효율적이거든요. 마치 날씨에 따라 다른 옷을 선택해서 입는 것과 같아요.
둘째로 기존 코드와의 소통을 원활하게 할 수 있습니다. 인터넷 세상의 많은 프로젝트들이 여전히 CommonJS를 사용하고 있어서, 이를 이해하지 못하면 다른 분들이 만든 코드와 대화하기 어려워요.
셋째로 최적의 성능을 얻을 수 있습니다. ES6 모듈은 브라우저에서 더 빠르게 작동하도록 설계되었고, CommonJS는 서버에서 더 유연하게 작동하도록 만들어졌거든요.
마지막으로 미래를 향한 준비를 할 수 있어요. ES6 모듈은 자바스크립트의 공식 표준이 되어가고 있으니, 미리 익혀두면 앞으로 많은 도움이 될 거예요.
⚙️ 문법 비교해보기
이제 두 방식이 실제로 어떻게 다른지 문법을 조심스럽게 비교해 보겠습니다.
CommonJS 방식 (우리가 함께 배워온 방식):
// 내보내기
module.exports = { add, subtract };
// 가져오기
const math = require('./math.js');
ES6 모듈 방식 (새로운 방식):
// 내보내기
export function add(a, b) { return a + b; }
// 가져오기
import { add } from './math.js';
보시다시피 키워드가 완전히 다르죠? CommonJS는 module.exports
와 require
를 사용하고, ES6 모듈은 export
와 import
를 사용해요.
🧪 예제로 차이점 경험하기
이제 실제 예제를 통해 두 방식의 차이점을 직접 느껴보겠습니다.
세상에는 많은 이야기가 있지만, 때로는 직접 경험해보는 것이 가장 확실한 이해의 길이 되기도 합니다. 지금부터 작은 예제들을 통해 두 방식의 차이를 천천히 살펴보겠습니다.
🔹 예제 1: 같은 기능, 다른 문법
먼저 똑같은 수학 함수를 두 가지 방식으로 만들어 비교해 보겠습니다.
CommonJS 방식으로 만든 수학 모듈:
// math.js 파일 (CommonJS 방식)
// 더하기 함수를 만들어요
function add(a, b) {
return a + b; // 두 숫자를 더해서 반환해요
}
// 곱하기 함수를 만들어요
function multiply(a, b) {
return a * b; // 두 숫자를 곱해서 반환해요
}
// 두 함수를 모듈로 내보내요
module.exports = {
add: add,
multiply: multiply
};
ES6 모듈 방식으로 만든 수학 모듈:
// math.mjs 파일 (ES6 모듈 방식)
// 더하기 함수를 만들면서 동시에 내보내요
export function add(a, b) {
return a + b; // 두 숫자를 더해서 반환해요
}
// 곱하기 함수도 만들면서 동시에 내보내요
export function multiply(a, b) {
return a * b; // 두 숫자를 곱해서 반환해요
}
두 방식 모두 같은 기능을 하지만, 문법이 완전히 다른 것을 볼 수 있어요. ES6 모듈은 함수를 만들면서 동시에 export
로 내보낼 수 있어서 조금 더 간결해 보이죠.
🔹 예제 2: 가져오는 방법도 달라요
이제 위에서 만든 수학 모듈을 가져와서 사용해 보겠습니다.
CommonJS 방식으로 가져오기:
// app.js 파일 (CommonJS 방식)
// math 모듈을 통째로 가져와요
const math = require('./math.js');
// 가져온 모듈의 함수를 사용해요
console.log("5 + 3 =", math.add(5, 3)); // 8
console.log("4 × 2 =", math.multiply(4, 2)); // 8
// 또는 필요한 함수만 선택해서 가져올 수도 있어요
const { add, multiply } = require('./math.js');
console.log("6 + 4 =", add(6, 4)); // 10
ES6 모듈 방식으로 가져오기:
// app.mjs 파일 (ES6 모듈 방식)
// 필요한 함수들을 선택해서 가져와요
import { add, multiply } from './math.mjs';
// 가져온 함수를 바로 사용해요
console.log("5 + 3 =", add(5, 3)); // 8
console.log("4 × 2 =", multiply(4, 2)); // 8
// 모든 함수를 한꺼번에 가져올 수도 있어요
// import * as math from './math.mjs';
// console.log("5 + 3 =", math.add(5, 3));
ES6 모듈은 처음부터 어떤 함수를 사용할지 명확하게 선언해야 해요. 마치 도서관에서 미리 목록을 작성하는 것처럼 말이죠.
🔹 예제 3: 기본 내보내기는 어떻게 다를까요?
주요 기능 하나를 기본으로 내보내는 방법도 비교해 보겠습니다.
CommonJS 방식의 기본 내보내기:
// calculator.js 파일 (CommonJS 방식)
// 계산기 객체를 만들어요
const calculator = {
name: "우리반 계산기",
add: function(a, b) {
return a + b; // 더하기 기능
},
subtract: function(a, b) {
return a - b; // 빼기 기능
}
};
// 계산기 전체를 기본으로 내보내요
module.exports = calculator;
// 사용하는 파일에서...
const myCalculator = require('./calculator.js');
console.log(myCalculator.name); // "우리반 계산기"
console.log(myCalculator.add(10, 5)); // 15
ES6 모듈 방식의 기본 내보내기:
// calculator.mjs 파일 (ES6 모듈 방식)
// 계산기 객체를 만들어요
const calculator = {
name: "우리반 계산기",
add: function(a, b) {
return a + b; // 더하기 기능
},
subtract: function(a, b) {
return a - b; // 빼기 기능
}
};
// 계산기를 기본으로 내보내요
export default calculator;
// 사용하는 파일에서...
import myCalculator from './calculator.mjs';
console.log(myCalculator.name); // "우리반 계산기"
console.log(myCalculator.add(10, 5)); // 15
기본 내보내기도 키워드만 다를 뿐 비슷한 방식으로 작동해요.
🔄 두 방식의 주요 차이점 정리
지금까지 배운 내용을 차근차근 정리해 보겠습니다.
언제 실행되나요?
CommonJS는 코드가 실행되는 도중에 필요할 때마다 모듈을 가져와요. ES6 모듈은 코드가 실행되기 전에 미리 모든 모듈을 확인하고 준비해요.
어디서 주로 사용하나요?
CommonJS는 주로 Node.js 서버에서 사용하고, ES6 모듈은 주로 웹 브라우저에서 사용해요.
파일 이름이 달라요
CommonJS는 .js
확장자를 사용하지만, ES6 모듈은 .mjs
확장자를 사용하거나 특별한 설정이 필요해요.
가져오는 방식이 달라요
CommonJS는 require()
로 언제든 가져올 수 있지만, ES6 모듈은 import
로 파일 맨 위에서만 가져올 수 있어요.
🧚♀️ 이야기로 다시 배우기: 두 친구의 서로 다른 정리법
지금까지 배운 내용을 따뜻한 이야기로 다시 정리해볼까요?
민수와 영희는 둘 다 책을 정말 좋아하는 친구들이에요. 하지만 책을 정리하는 방법이 완전히 달라요.
민수(CommonJS 방식)는 책이 필요할 때마다 책장에 가서 찾아요. "오늘은 과학책이 필요하네"라고 생각하면 바로 책장으로 가서 과학책을 꺼내서 사용하죠. 매우 자유롭고 편안하지만, 때로는 책을 찾는 데 시간이 걸려요.
영희(ES6 모듈 방식)는 하루가 시작되기 전에 미리 오늘 필요한 모든 책을 책상 위에 정리해 놓아요. "오늘은 수학책, 과학책, 국어책이 필요해"라고 계획을 세우고, 아침에 모든 책을 미리 준비해두죠. 조금 더 계획적이어야 하지만, 실제로 공부할 때는 매우 빠르고 효율적이에요.
두 방법 모두 저마다의 장점이 있어요. 민수의 방법은 자유롭고 유연하고, 영희의 방법은 체계적이고 빨라요. 상황에 따라 어떤 방법이 더 좋을지 선택할 수 있답니다.
🧠 자주 하는 실수와 주의할 점
두 방식을 사용할 때 자주 하는 실수들을 미리 알아두면 도움이 될 거예요.
❌ 실수 1: 두 방식을 섞어서 사용하기
// 이렇게 하면 안 돼요!
const math = require('./math.js'); // CommonJS 방식
import { add } from './other.mjs'; // ES6 모듈 방식
한 파일에서 require
와 import
를 함께 사용하면 자바스크립트가 혼란스러워해서 오류가 발생해요. 하나의 파일에서는 한 가지 방식만 사용해야 해요.
❌ 실수 2: 파일 확장자 혼동하기
// ES6 모듈을 사용하고 싶은데 .js 확장자를 그대로 쓰면...
import { func } from './module.js'; // 특별한 설정 없이는 작동하지 않을 수 있어요
ES6 모듈을 Node.js에서 사용하려면 .mjs
확장자를 사용하거나, 특별한 설정 파일에서 설정을 해주어야 해요.
❌ 실수 3: import를 함수 안에서 사용하려고 하기
// 이렇게 하면 안 돼요!
function someFunction() {
import { add } from './math.mjs'; // 에러 발생!
}
ES6 모듈의 import
는 항상 파일의 맨 위에 있어야 해요. 함수 안이나 조건문 안에서는 사용할 수 없어요.
✏️ 연습문제로 개념 다지기
코드를 써내려가는 일은 때로 시를 쓰는 것과 닮아있습니다. 각각의 줄이 서로를 보완하며 하나의 완전한 이야기를 만들어내죠. 이제 배운 내용을 연습문제를 통해 천천히 익혀보겠습니다.
Ex1) 동일한 기능을 두 방식으로 만들어 "같은 기능, 다른 문법을 비교해보자!"
// CommonJS 방식 (greetings.js)
function sayHello(name) {
return `안녕하세요, ${name}님!`; // 인사말을 반환해요
}
function sayGoodbye(name) {
return `안녕히 가세요, ${name}님!`; // 작별 인사를 반환해요
}
// 두 함수를 내보내요
module.exports = {
sayHello: sayHello,
sayGoodbye: sayGoodbye
};
// ES6 모듈 방식 (greetings.mjs)
export function sayHello(name) {
return `안녕하세요, ${name}님!`; // 인사말을 반환해요
}
export function sayGoodbye(name) {
return `안녕히 가세요, ${name}님!`; // 작별 인사를 반환해요
}
Ex2) 위에서 만든 모듈을 가져와서 "두 가지 방법으로 사용해보자!"
// CommonJS 방식으로 사용하기 (app.js)
const greetings = require('./greetings.js');
console.log(greetings.sayHello('민수')); // "안녕하세요, 민수님!"
console.log(greetings.sayGoodbye('영희')); // "안녕히 가세요, 영희님!"
// ES6 모듈 방식으로 사용하기 (app.mjs)
import { sayHello, sayGoodbye } from './greetings.mjs';
console.log(sayHello('민수')); // "안녕하세요, 민수님!"
console.log(sayGoodbye('영희')); // "안녕히 가세요, 영희님!"
Ex3) 기본 내보내기를 연습해서 "메인 기능 하나를 내보내보자!"
// CommonJS 방식 (student.js)
const student = {
name: "철수",
age: 11,
grade: 5,
introduce: function() {
return `안녕하세요! 저는 ${this.grade}학년 ${this.name}입니다.`;
}
};
module.exports = student; // 학생 객체를 기본으로 내보내요
// 사용하기
const myStudent = require('./student.js');
console.log(myStudent.introduce()); // "안녕하세요! 저는 5학년 철수입니다."
// ES6 모듈 방식 (student.mjs)
const student = {
name: "철수",
age: 11,
grade: 5,
introduce: function() {
return `안녕하세요! 저는 ${this.grade}학년 ${this.name}입니다.`;
}
};
export default student; // 학생 객체를 기본으로 내보내요
// 사용하기
import myStudent from './student.mjs';
console.log(myStudent.introduce()); // "안녕하세요! 저는 5학년 철수입니다."
🤔 심화 문제로 실력 확인하기
때로는 가장 깊은 이해는 조금 더 어려운 문제들과 마주했을 때 찾아옵니다. 기본 연습을 마쳤다면, 이제 조금 더 깊이 있는 문제들을 통해 두 방식에 대한 이해를 확인해보겠습니다.
Q1. 다음 ES6 모듈 코드를 CommonJS 방식으로 바꿔서 "코드 변환에 도전해보자!"
// 변환할 ES6 모듈 코드
export const PI = 3.14159; // 원주율 상수
export function calculateArea(radius) { // 원의 넓이 계산 함수
return PI * radius * radius;
}
export default function createCircle(radius) { // 원 객체 생성 함수 (기본 내보내기)
return {
radius: radius,
area: calculateArea(radius)
};
}
정답:
// CommonJS로 변환한 코드
const PI = 3.14159; // 원주율 상수
function calculateArea(radius) { // 원의 넓이 계산 함수
return PI * radius * radius;
}
function createCircle(radius) { // 원 객체 생성 함수
return {
radius: radius,
area: calculateArea(radius)
};
}
// 내보내기
module.exports = createCircle; // 기본 내보내기
module.exports.PI = PI; // 개별 내보내기 추가
module.exports.calculateArea = calculateArea;
해설: ES6 모듈에서 export
로 내보낸 각각의 요소들을 CommonJS에서는 module.exports
의 속성으로 추가했어요. 기본 내보내기(export default
)는 module.exports
에 직접 할당하고, 나머지는 속성으로 추가했습니다.
Q2. 두 방식의 장단점을 3가지씩 설명해서 "어떤 상황에서 무엇을 쓸지 알아보자!"
CommonJS의 장점:
- 사용이 간단해요: 특별한 설정 없이 Node.js에서 바로 사용할 수 있어서 배우기 쉬워요.
- 유연하게 사용할 수 있어요: 필요할 때마다 조건에 따라 다른 모듈을 가져올 수 있어요.
- 많은 패키지가 지원해요: npm의 대부분 패키지가 CommonJS로 만들어져 있어서 호환성이 좋아요.
CommonJS의 단점:
- 브라우저에서 직접 사용할 수 없어요: 웹페이지에서 사용하려면 특별한 도구가 필요해요.
- 느릴 수 있어요: 모듈을 가져올 때마다 처리하기 때문에 속도가 느려질 수 있어요.
- 최적화가 어려워요: 사용하지 않는 코드를 자동으로 제거하기 어려워요.
ES6 모듈의 장점:
- 빠르고 효율적이에요: 미리 모든 것을 준비해서 실행할 때 매우 빨라요.
- 안전해요: 실행 전에 오류를 미리 발견할 수 있어서 더 안전해요.
- 표준이에요: 자바스크립트의 공식 표준이라서 앞으로 계속 발전할 거예요.
ES6 모듈의 단점:
- 설정이 복잡해요: Node.js에서 사용하려면 추가 설정이나 확장자 변경이 필요해요.
- 유연성이 부족해요: 모든 것을 미리 선언해야 해서 즉석 사용이 어려워요.
- 호환성 문제가 있어요: 오래된 환경에서는 지원되지 않을 수 있어요.
지금까지 CommonJS와 ES6 모듈의 차이점에 대해 함께 살펴보았습니다. 두 방식 모두 각각의 아름다움이 있으니, 상황에 맞게 적절한 방식을 선택해서 사용하면 됩니다. 마치 상황에 따라 다른 악기를 선택해서 연주하는 것처럼 말이에요.
📝 복습 문제 - 이전 단원 내용 기억하기
새로운 내용을 배우는 것만큼이나 이전에 배운 소중한 내용들을 되새기는 것도 중요해요. 이번 시간에 새로운 내용을 배웠으니, 이전에 배운 중요한 내용도 함께 복습해볼까요?
🔢 모듈 시스템의 장점 복습 (17.2단원에서 배운 내용)
문제 1: 모듈 시스템을 사용하는 이유 3가지를 설명해보세요.
해답:
- 코드 재사용성: 한 번 만든 코드를 여러 곳에서 재사용할 수 있어서 중복을 줄이고 효율적으로 개발할 수 있어요.
- 이름 충돌 방지: 서로 다른 모듈의 변수나 함수가 충돌하지 않도록 분리해서 관리할 수 있어요.
- 코드 관리: 어떤 코드가 어떤 다른 코드를 필요로 하는지 명확하게 알 수 있어서 관리가 쉬워요.
🔧 CommonJS 기본 복습 (17.3.1, 17.3.2단원에서 배운 내용)
문제 2: CommonJS에서 모듈을 내보내고 가져오는 기본 문법을 작성해보세요.
해답:
// math.js - 모듈 내보내기
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
// 여러 함수 내보내기
module.exports = {
add: add,
subtract: subtract
};
// 또는 하나씩 내보내기
// module.exports.add = add;
// module.exports.subtract = subtract;
// app.js - 모듈 가져오기
const math = require('./math.js'); // 전체 모듈 가져오기
const { add, subtract } = require('./math.js'); // 선택적 가져오기
console.log(math.add(5, 3)); // 8
console.log(subtract(10, 4)); // 6
해설: CommonJS에서는 module.exports
로 내보내고 require()
로 가져와요. 객체 형태로 여러 함수를 한 번에 내보낼 수도 있고, 구조 분해 할당으로 필요한 것만 선택해서 가져올 수도 있어요.
✅ 학습 완료 체크리스트
이번 시간에 배운 내용들을 모두 이해했는지 확인해보세요!
학습 내용 | 이해했나요? |
---|---|
CommonJS와 ES6 모듈의 기본 개념 | ✅ |
두 방식의 문법 차이 | ✅ |
장단점과 사용 환경 | ✅ |
자주 하는 실수들 | ✅ |
실전 예제 이해 | ✅ |
📂 마무리 정보
오늘 배운 17.3.3
내용이 여러분의 자바스크립트 지식 상자에 잘 저장되었나요? CommonJS와 ES6 모듈은 각각 다른 상황에서 유용하니까, 두 방식의 차이점을 잘 기억해두세요. 다음 시간에는 더 흥미로운 내용으로 만나요!
기억할 점: 두 방식 모두 코드를 나누고 공유하는 같은 목적을 가지고 있지만, 사용 환경과 문법이 다르다는 점을 꼭 기억해두세요.
무료 JavaScript 학습 플랫폼에서 단계별 학습과 실시간 코드 실행을 통해
더욱 효과적이고 재미있게 학습하실 수 있습니다.
'17. 코드 정리하고 나누기 (모듈 시스템) > 17.3 CommonJS (Node.js 방식)' 카테고리의 다른 글
17.3.2 require로 불러오기 - 편리한 배달 서비스 (0) | 2025.07.25 |
---|---|
17.3.1 module.exports 사용하기 - Node.js의 특별한 선물상자 (0) | 2025.07.25 |