Node.js import, require 차이점은? ESM vs CommonJS 실전 예제
Node.js 프로젝트를 하다 보면 import를 썼더니 오류가 나고, require를 쓰면 또 다른 문제가 생기는 경우가 많습니다.
Node.js에서 import와 require는 어떤 차이가 있고, 각각 언제 사용해야 할까요?
이 글에서는 CommonJS와 ES Modules(ECMAScript Modules)의 차이, 실제 사용 예제, 그리고 스마트베이 실무 경험 기반의 문제 해결 방법까지 함께 정리해드립니다.
1. Node.js에서 import와 require가 혼용되는 이유는?
const express = require('express'); // CommonJS
// 또는
import express from 'express'; // ES Modules
Node.js 공식 문서나 StackOverflow에서 두 문법이 섞여 있는 걸 자주 보게 됩니다.
왜 이렇게 혼용되는 걸까요? 그 이유는 Node.js가 두 가지 모듈 시스템을 모두 지원하기 때문입니다.
2. CommonJS와 ES Modules의 등장 배경
CommonJS: Node.js의 전통적인 모듈 시스템
Node.js 초창기에는 브라우저에서 사용되던 ES6 모듈 시스템이 존재하지 않았습니다.
그래서 자체적으로 만든 모듈 시스템이 바로 CommonJS입니다.
- 모듈 가져오기: require('모듈명')
- 모듈 내보내기: module.exports = ...
ES Modules: 브라우저와의 통합을 위한 새 표준
ES6(ES2015)에서 공식적으로 도입된 모듈 시스템이며, Node.js도 점차 이를 채택하게 됩니다.
- 모듈 가져오기: import ... from '모듈명'
- 모듈 내보내기: export default, export { ... }
브라우저와 Node.js를 모두 아우르는 통합된 모듈 방식이 필요해졌고, ES Modules는 이를 해결하기 위해 등장했습니다.
3. CommonJS vs ES Modules 차이점
| 항목 | CommonJS (CJS) | ES Modules (ESM) |
|---|---|---|
| 구문 | require() / module.exports |
import / export |
| 실행 방식 | 동기(Synchronous) | 비동기(Asynchronous) |
| 기본 확장자 | .js, .cjs | .mjs, 또는 "type": "module" |
| __dirname 사용 | 지원됨 | 기본 미지원 |
| 동적 로딩 | 가능 | import() 필요 |
요약: CommonJS는 동기식 실행, ES Modules는 비동기식 처리와 top-level await 사용 가능
4. 실전 예제로 이해하는 사용법
CommonJS 방식
// file: server.cjs
const http = require('http');
http.createServer((req, res) => {
res.end('Hello from CommonJS!');
}).listen(3000);
ES Modules 방식
// file: server.mjs
import http from 'http';
const server = http.createServer((req, res) => {
res.end('Hello from ES Modules!');
});
server.listen(3000);
.mjs 확장자 또는 package.json에 "type": "module" 설정이 필요합니다.
5. 실무에서 자주 발생하는 오류 및 해결 방법
오류 1: SyntaxError: Cannot use import statement outside a module
원인: .js 파일에서 import를 사용했지만, type: "module"이 설정되지 않은 경우
// package.json
{
"type": "module"
}
오류 2: require is not defined
원인: ES Modules 환경에서는 require가 기본으로 제공되지 않음
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const fs = require('fs');
실전 Q&A: StackOverflow 예시
Q. 기존 CommonJS 프로젝트를 ES Modules로 마이그레이션 중인데, __dirname이 안 돼요!
A. ES Modules에서는 __dirname이 제공되지 않기 때문에, 아래와 같이 구현해야 합니다:
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
스마트베이에서도 기존 CommonJS 기반 툴을 ESM으로 전환하는 과정에서 __dirname 문제를 겪었고, 위 방식으로 안정적으로 해결했습니다.
6. 정리 및 추천 가이드라인
- 새 프로젝트라면 ES Modules 권장
- 기존 CommonJS 프로젝트는 혼합 사용 최소화
- 외부 라이브러리와의 호환성 주의
.cjs/.mjs확장자 구분 필요
이 내용은 스마트베이 내부 코드베이스 개선 과정에서 얻은 실무 인사이트를 기반으로 작성되었습니다.
실제 운영 중인 Node.js 자동화 서비스에서 발생한 오류를 해결하며 축적한 경험을 정리한 것이므로, 유사한 상황에서도 유용하게 적용될 수 있습니다.
마무리: import와 require, 이제는 구분해서 써야 합니다
Node.js는 이제 두 개의 모듈 시스템을 공식 지원합니다.
중요한 건 혼합 사용은 최소화하고, 프로젝트 성격에 맞게 일관되게 사용하는 것입니다.
에러가 나더라도 당황하지 말고, 오늘 설명드린 방식으로 해결해보세요!
함께 읽으면 좋은 글
비즈니스 효율을 높이는 스마트한 IT 솔루션을 제공합니다.
웹사이트 : www.esmartbay.co.kr
E-mail : smartbay.svc@gmail.com
카카오톡 : 바로 상담하기
'프로그래밍 > NodeJS' 카테고리의 다른 글
| Node.js 프로젝트에서 모듈 정리와 최적화하는 방법 (2) | 2025.07.12 |
|---|---|
| npm install 명령어의 동작 원리 - 단순 명령어 뒤에 숨겨진 비밀 (3) | 2025.06.14 |
| 초보 개발자를 위한 package.json 구성요소 쉽게 이해하기 (2) | 2025.06.13 |