모듈이 뭐임?
모듈은 쉽게 말해서 레고 블록 같은 것
프로그램을 만들 때 모든 코드를 한 파일에 다 때려 넣으면 너무 복잡하고 관리하기 어려움.
그래서 기능별로 코드를 나눠서 다른 파일로 만들고, 필요할 때 가져다 쓰는 것
예를 들어:
- `math.js` → 수학 계산 기능
- `user.js` → 사용자 관리 기능
- `database.js` → 데이터베이스 연결 기능
이렇게 나눠두면 재사용도 쉽고, 유지보수도 편함!
Node.js의 두 가지 모듈 시스템
Node.js에는 모듈을 사용하는 방법이 2가지 있음:
| 구분 | CommonJS (CJS) | ES Module (ESM) |
| 사용 키워드 | `require` / `module.exports` | `import` / `export` |
| 등장 시기 | Node.js 초기부터 | 최신 JavaScript 표준 |
| 파일 확장자 | `.js` (기본) | `.mjs` 또는 `.js` (package.json 설정 필요) |
| 로딩 방식 | 동기(Synchronous) | 비동기(Asynchronous) |
| 브라우저 지원 | (Node.js 전용) | (최신 브라우저 지원) |
1. 모듈 만들기 (Export)
`math.js` 파일
먼저 수학 계산 기능을 모아둔 모듈을 만들어보겠음
1. CommonJS 방식 (구식이지만 아직 많이 씀)
// 덧셈 함수
function add(a, b) {
return a + b;
}
// 뺄셈 함수
function sub(a, b) {
return a - b;
}
// CommonJS 방식으로 내보내기
module.exports = {
add, // 키와 값이 같으면 하나만 써도 됨 (add: add 와 동일)
sub,
};
설명
- `module.exports`는 "이 파일에서 이것들을 내보낼게!"라고 선언하는 것
- 객체 형태로 여러 함수를 한 번에 내보낼 수 있음
- 키와 변수명이 같으면 생략 가능 (ES6 단축 속성)
2. ES Module 방식 (최신 방식, 요즘 트렌드!)
// 방법 1: 함수 정의 후 한번에 export
function add(a, b) {
return a + b;
}
function sub(a, b) {
return a - b;
}
export { add, sub };
// 방법 2: 함수 정의할 때 바로 export (더 간단!)
export function add(a, b) {
return a + b;
}
export function sub(a, b) {
return a - b;
}
설명
- `export` 키워드로 함수를 내보냄
- 함수 선언 앞에 바로 붙이거나, 나중에 한꺼번에 내보낼 수 있음
- 각각의 함수를 Named Export(이름이 있는 내보내기)라고 부름
3. Default Export (대표 선수 정하기)
// 이 모듈의 대표 함수 (곱셈)
export default function multiply(a, b) {
return a * b;
}
설명:
- `default`는 "이 모듈의 대표 기능이야!"라고 지정하는 것
- 파일당 딱 1개만 가능
- 가져올 때 이름을 마음대로 바꿀 수 있음
4. 다양한 것들 내보내기
// 나눗셈 함수
export function divide(a, b) {
if (b === 0) {
return "0으로 나눌 수 없습니다";
}
return a / b;
}
// 거듭제곱 함수
export function power(a, b) {
return Math.pow(a, b);
}
// 상수도 export 가능!
export const PI = 3.14159;
설명
- 함수뿐만 아니라 변수, 상수, 클래스 등 뭐든지 내보낼 수 있음
- `const`, `let`, `var` 앞에 `export`를 붙이면 됨
2. 모듈 가져다 쓰기 (Import)
`index.js` 파일
이제 만들어둔 모듈을 가져와서 사용해볼 것
1. CommonJS 방식으로 가져오기
// 방법 1: 전체를 객체로 받기
const moduleData = require("./math");
console.log(moduleData.add(1, 2)); // 3
console.log(moduleData.sub(1, 2)); // -1
// 방법 2: 구조 분해 할당으로 필요한 것만 받기 (더 깔끔!)
const { add, sub } = require("./math");
console.log(add(1, 2)); // 3
console.log(sub(1, 2)); // -1
설명
- `require()`로 다른 파일의 모듈을 가져옴
- 구조 분해 할당을 쓰면 필요한 함수만 꺼내 쓸 수 있음
- ./는 "현재 폴더"를 의미함
2. ES Module 기본 import
// Default export 가져오기
import multiply from "./math.js";
// Named export 가져오기
import { add, sub } from "./math.js";
console.log("=== 기본 import ===");
console.log(add(1, 2)); // 3
console.log(sub(1, 2)); // -1
console.log(multiply(3, 4)); // 12
설명
- ES Module에서는 `.js` 확장자를 반드시 써야 함
- Default export는 `{}`없이 가져오고, Named export는 `{}`로 감싸서 가져옴
- 한 줄에 여러 개를 import할 수 있음
3. 별칭(Alias) 사용하기
import { add as plus, sub as minus } from "./math.js";
console.log("\n=== 별칭 사용 ===");
console.log(plus(5, 3)); // 8
console.log(minus(5, 3)); // 2
설명
- `as` 키워드로 가져올 때 이름을 바꿀 수 있음
- 이름이 겹치거나, 더 직관적인 이름을 쓰고 싶을 때 유용함
- `add`를 `plus`라는 이름으로 사용 가능
4. 전체 import (와일드카드)
import * as math from "./math.js";
console.log("\n=== 전체 import (*) ===");
console.log(math.add(10, 5)); // 15
console.log(math.sub(10, 5)); // 5
console.log(math.default(2, 6)); // 12 (default export는 .default로 접근)
설명
- `* as 이름` 형태로 모든 export를 한 번에 가져올 수 있음
- 모든 함수가 `math` 객체의 속성이 됨
- Default export는 `.default`로 접근해야 함 (주의!)
5. 추가 함수들 사용하기
import { divide, power, PI } from "./math.js";
console.log("\n=== 추가 함수들 ===");
console.log(divide(10, 2)); // 5
console.log(divide(10, 0)); // "0으로 나눌 수 없습니다"
console.log(power(2, 3)); // 8
console.log(PI); // 3.14159
설명:
- 필요한 것만 골라서 가져올 수 있음
- 상수(`PI`)도 똑같이 import 가능
- 에러 처리가 되어있는 함수는 안전하게 사용 가능
6. Default + Named Export 동시에 가져오기
import multiply2, { add as addition, divide as div } from "./math.js";
console.log("\n=== Default + Named 동시 import ===");
console.log(multiply2(4, 5)); // 20
console.log(addition(100, 200)); // 300
console.log(div(20, 4)); // 5
설명
- Default export와 Named export를 한 줄에 동시에 가져올 수 있음
- Default는 앞에, Named는 `{}` 안에 작성
- 별칭도 함께 사용 가능
핵심 정리
CommonJS vs ES Module 비교
| 비교 항목 | CommonJS | ES Module |
| 내보내기 | `module.exports = { }` | `export` / `export default` |
| 가져오기 | `require()` | `import` / `import from` |
| 확장자 | `.js` (생략 가능) | `.js` (생략 불가) |
| 실행 시점 | 런타임에 동기 로딩 | 파일 파싱 시 정적 로딩 |
| 사용 환경 | Node.js 전용 | Node.js + 브라우저 |
Export 종류
| 종류 | 문법 | 특징 |
| Named Export | `export function func() {}` | 이름 그대로 import 해야 함, 여러 개 가능 |
| Default Export | `export default function() {}` | 파일당 1개만, import 시 이름 자유롭게 |
Import 방법 총정리
// 1. Default import
import multiply from "./math.js";
// 2. Named import
import { add, sub } from "./math.js";
// 3. 별칭 사용
import { add as plus } from "./math.js";
// 4. 전체 import
import * as math from "./math.js";
// 5. Default + Named 동시
import multiply, { add, sub } from "./math.js";
// 6. Default + Named + 별칭 조합
import multiply, { add as plus, sub as minus } from "./math.js";
사용 팁
ES Module 사용하기 (package.json 설정)
ES Module을 사용하려면 package.json에 다음을 추가해야 함
{
"type": "module"
}
또는 파일 확장자를 `.mjs`로 변경하면 됨
주의사항
1. ES Module에서는 확장자 필수!
// 안됨
import { add } from "./math";
// 됨
import { add } from "./math.js";
2. CommonJS와 ES Module은 섞어 쓸 수 없음
- 한 프로젝트에서는 하나의 방식으로 통일하는 게 좋음
3. Default export는 파일당 1개만!
// 안됨
export default function add() {}
export default function sub() {} // 에러!
어떤 걸 써야 할까?
CommonJS를 쓰는 경우:
- 오래된 Node.js 프로젝트
- npm 패키지들이 대부분 CommonJS일 때
- 동적 import가 필요할 때 (`require()`는 조건문 안에서도 사용 가능)
ES Module을 쓰는 경우:
- 새로운 프로젝트 시작할 때 (요즘 트렌드!)
- 브라우저와 Node.js 모두에서 코드를 돌릴 때
- 최신 JavaScript 문법을 사용하고 싶을 때
- React, Vue 같은 프레임워크 사용할 때
'React > Node.js' 카테고리의 다른 글
| [Node.js] Node.js 소개 및 설정 (0) | 2025.11.12 |
|---|