javascript module import export 실무 가이드: 개념과 적용 방법
javascript module import export의 핵심 개념과 실무 적용법을 정리합니다. ES 모듈, CommonJS, 동적 임포트, 번들러 설정, 주의점까지 사례와 체크리스트로 바로 적용 가능한 실무 가이드를 제공합니다.
javascript module import export이 필요한 상황
javascript module import export는 코드 모듈화를 통해 유지보수성과 재사용성을 높이고, 번들 크기 최적화와 로드 성능 개선을 위해 필요합니다. 이 글에서는 ES 모듈과 CommonJS의 차이, named/default export, dynamic import 사용법, 번들러 설정 예제와 실전에서의 주의점까지 실무 관점으로 다룹니다. 읽고 나면 프로젝트에 적절한 모듈 방식 선택, 코드 작성 패턴, 배포 시 점검 포인트를 바로 적용할 수 있습니다.
javascript module import export 핵심 개념
- ES Modules(ESM): import/export 키워드를 사용. 정적 분석이 가능해 트리 쉐이킹(tree shaking)과 정적 바인딩에 유리.
- CommonJS(CJS): require/module.exports 사용. Node 환경에서 널리 사용되며 런타임에 결합.
- Default vs Named Export: 모듈당 하나의 default와 여러 named를 허용. 사용 패턴에 따라 가독성 또는 명시성이 달라짐.
- Dynamic import(): 런타임에 모듈을 비동기로 로드. 코드 스플리팅과 초기 로드 지연에 유리.
용어 정리:
- 트리 쉐이킹: 사용하지 않는 코드를 번들에서 제거하는 최적화
- 코드 스플리팅: 번들을 여러 조각으로 나눠 필요할 때만 로드
javascript module import export 실무 예제
다음 예제는 ES 모듈을 기준으로 한 실무 코드입니다. React/Next.js뿐 아니라 일반 웹 애플리케이션에도 적용 가능한 패턴입니다.
// utils/math.js export function add(a, b) { return a + b; } export const PI = 3.14159; // utils/logger.js export default function logger(msg) { console.log(`[LOG] ${msg}`); } // 사용 예: index.js import logger from './utils/logger.js'; import { add, PI } from './utils/math.js'; logger('Start app'); console.log(add(2, 3), PI); // dynamic import 예제 async function loadChart() { const { Chart } = await import('./vendor/chart-lib.js'); const c = new Chart('#canvas'); return c; } loadChart();
번들러(예: Webpack, Vite) 설정에서 ESM을 사용하면 트리 쉐이킹이 더 잘 동작합니다. CommonJS 모듈을 ESM과 함께 사용할 때는 default 인터옵(interop) 처리가 필요할 수 있습니다.
ESM vs CommonJS 비교 기준
| 구분 | 항목1 | 항목2 | 항목3 |
|---|---|---|---|
| 내용 | 정적 분석 가능 | 런타임 결합 | 트리 쉐이킹 지원 |
| 내용 | 브라우저 네이티브 지원 | Node 기존 생태계 | dynamic import 가능 |
위 표는 ESM과 CommonJS의 핵심 차이를 빠르게 비교하기 위한 기준표입니다.
언제 쓰면 좋고 언제 피해야 할까
언제 쓰면 좋은가:
- 최신 브라우저 환경과 번들러를 사용하는 프론트엔드 프로젝트
- 트리 쉐이킹으로 번들 크기 최적화가 필요한 경우
- 코드 스플리팅, lazy loading으로 초기 로드 시간을 줄이고자 할 때
언제 피해야 하는가:
- 레거시 Node.js 버전(예: ESM 지원 이전)을 그대로 사용하는 서버 사이드 코드
- 라이브러리 호환성 문제로 CommonJS만 지원하는 서드파티 의존성이 많은 경우
- 빌드 파이프라인을 변경할 수 없고 ESM로 마이그레이션 비용이 클 때
실무 체크리스트
- 프로젝트에서 ESM을 기본으로 사용할지 CommonJS를 유지할지 결정했는가?
- 번들러(예: Vite, Webpack) 설정이 ESM 기반 트리 쉐이킹을 지원하도록 구성되었는가?
- default와 named export의 사용 규칙을 팀 규약으로 정했는가?
- dynamic import 사용 시 오류 핸들링과 로딩 UX(스켈레톤/스피너)를 구현했는가?
- 서버 사이드(예: Node)와 클라이언트 사이드에서 모듈 호환성을 확인했는가?
- 번들 분석 도구(예: webpack-bundle-analyzer)로 빌드 결과를 주기적으로 점검하는가?
체크리스트를 참고해 코드 규약과 빌드 파이프라인을 정비하세요.
성능·보안·운영 주의점
성능
- 트리 쉐이킹이 제대로 작동하려면 side-effect-free 모듈 작성이 필요합니다. package.json에 "sideEffects": false를 적절히 설정하세요.
- dynamic import는 초기 번들 크기를 줄이지만 네트워크 요청이 늘어나므로 요청 수/지연을 고려해야 합니다.
보안
- 동적 import로 외부 URL에서 스크립트를 로드하는 경우 공급망 공격에 취약합니다. 서명 검증이나 신뢰할 수 있는 CDN 사용을 권장합니다.
- 빌드 시 서드파티 의존성의 취약점(Vuln)을 정기적으로 스캔하세요.
운영
- Node 환경에서 ESM로 전환할 때 파일 확장자(.mjs vs .js)와 package.json의 "type" 필드 영향을 확인하세요.
- 번들 변경 시 캐시 무효화 전략(파일명 해싱 등)을 도입해 브라우저 캐시 문제를 방지하세요.
javascript module import export 마이그레이션 예시
- 단계 1: 코드베이스에서 named export 사용 권장, default는 필요 시 유지
- 단계 2: package.json에 "type": "module" 추가(서버 ESM 전환 시)
- 단계 3: 번들러 설정 검토 및 테스트 환경(테스트 러너) ESM 지원 확인
- 단계 4: 점진적으로 dynamic import로 코드 스플리팅 적용
자주 묻는 질문
Q: CommonJS와 ES Modules를 혼용해도 되나요? A: 혼용은 가능하지만 interop 문제가 발생할 수 있어 권장하지 않습니다. 점진적 전환 시에는 명확한 변환 규칙과 테스트가 필요합니다.
Q: default export가 나쁜가요? A: 나쁘지는 않지만 named export가 리팩터링과 자동 완성 측면에서 유리합니다. 팀 컨벤션에 따라 사용하세요.
Q: dynamic import는 모든 브라우저에서 안전한가요? A: 최신 브라우저는 지원하지만 구형 브라우저는 폴리필이나 서버 사이드 폴백이 필요할 수 있습니다. 크로스 브라우저 테스트가 필요합니다.
Q: package.json의 "type": "module"을 설정하면 무엇이 바뀌나요? A: .js 파일을 ESM으로 해석합니다. 기존 CommonJS 코드는 .cjs 확장자로 유지해야 충돌을 피할 수 있습니다.
정리
- javascript module import export는 모듈화, 트리 쉐이킹, 코드 스플리팅에 핵심적이다.
- ES Modules(ESM)은 정적 분석과 트리 쉐이킹에 유리하고, CommonJS는 기존 Node 생태계와 호환된다.
- dynamic import로 런타임 코드 스플리팅을 구현할 수 있으나 네트워크 비용을 고려해야 한다.
- 마이그레이션 시 package.json의 "type" 설정, 번들러 구성, 서드파티 호환성을 점검해야 한다.
- 체크리스트와 보안/운영 주의점을 반영해 팀 규약과 CI 파이프라인을 정비하라.