내부 개발 서버에서 chart.js(v4.4.7)를 새로 도입하던 중, @kurkle/color 의존성 문제로 인해 이슈가 발생했습니다.
-
chart.cjs가 내부적으로 @kurkle/color 모듈을 찾지 못하는 오류였고, 이는 chart.js가 @kurkle/color를 의존성으로 가지고 있는데 chart.js만 직접 다운받아 ESM 방식으로 진행했을 때 문제가 없이 넘어갔는데 인터넷이 되지 않는 내부망에서 빌드를 하려고 하니 이슈가 발생하였습니다.
-
특이한 점은 package.json에 “type”: “module” 설정이 되어 있고 번들러 설정도 로컬과 동일함에도 불구하고 내부망 환경에서만 CJS 방식으로 동작해 chart.cjs가 불려나가는 상황이 발생했다는 것입니다. 로컬 환경에서는 문제가 없었는데 왜 내부망 환경에서만 이런 현상이 발생하는지는 아직 원인을 찾지 못했습니다.
UMD 번들(chart.umd.js, chart.umd.min.js) 사용 시 해결
UMD 번들 파일을 사용하면, @kurkle/color 같은 의존성이 모두 하나로 묶여서 제공되므로 참조 이슈 없이 정상적으로 동작합니다.
다만, UMD 파일 사용 시에는 패키지의 내부 폴더 경로나 /auto 엔트리를 통한 환경 자동 인식을 지원하지 않습니다.
예) import Chart from '/your/path/chart.umd.min.js/auto';
와 같은 방식은 UMD 빌드에서 불가능합니다.
가능한 해결책
1. 직접 script 태그로 로드 후 window 객체에서 접근
//jsp 단에서 미리 로드
<script type="text/javascript" src="/your/path/chart.umd.min.js"></script>
//이후 window.Chart로 접근
const Chart = window.Chart;
// 이후 Chart 사용
위 방식은 급한 불을 끌 수 있는 임시방편이긴 하지만 다음과 같은 이유로 권장되지는 않습니다:
-
모듈 시스템과 동떨어짐: 전역 스코프(window.Chart)를 사용하기 때문에 ESM(ECMAScript Modules)이나 CommonJS 기반의 모듈형 설계와 어긋나 관리가 어려워집니다.
-
전역 변수 충돌 우려: 전역 스코프에 등록된 객체 이름(Chart)이 다른 라이브러리나 코드와 충돌할 가능성이 있습니다.
-
트리쉐이킹(Tree Shaking) 불가: 모듈 단위로 불필요한 코드를 제거하기 어렵고 번들 크기 최소화에도 제약이 생깁니다.
-
버전 관리의 복잡성: 특정 버전을 교체할 때마다 HTML 스크립트 태그 경로를 직접 바꿔야 하고 여러 프로젝트에서 공유 시 충돌이나 의존성 문제를 파악하기가 까다롭습니다.
따라서 장기적으로는 ESM/CJS 등을 사용하여 모듈성을 유지하는 편이 유지보수와 확장성 면에서 유리하기 때문에 다른 방법을 찾아봤습니다.
2. ESM Wrapper로 번들링하여 사용
-
rollup, webpack, esbuild 등을 이용해 UMD 파일을 ESM 형태로 재번들링할 수 있습니다.
-
실제로 Chart.js 일부 버전은 rollup 설정이 포함되어 자동 변환이 이뤄지는 경우도 있습니다.
-
예를 들어 4.1.2, 4.1.0 등 특정 버전에서 chart.umd.js를 import 형태로 직접 불러와 사용할 수 있다는 사례가 있으니 사용하는 버전에 따라 테스트가 필요합니다.(저는 4.1.2 버전을 사용하였습니다.)
결론
내부망 환경에서의 새 패키지 추가 시 주의사항
• UMD 빌드를 우선 검토: 다른 환경(CJS, ESM 등)에서 경로나 의존성 충돌이 날 가능성을 줄일 수 있습니다.
• 문서(릴리스 노트) 꼼꼼히 확인: Chart.js 버전별로 빌드 구조와 의존성 처리 방식이 달라서 도입 전후로 관련 변경사항을 반드시 살펴봐야 합니다.
• “왜 동일 설정(로컬과 같은 번들러, type: ‘module’)임에도 내부망에서만 CJS 모드로 동작했는지”는 명확한 원인을 찾지 못했습니다. 이건 계속 찾아볼 것 같습니다.
• 일단 UMD 빌드 사용(혹은 ESM 빌드로 재번들링)으로 문제를 우회할 수 있었고 버전별 차이가 커서 문서 확인 및 사전 테스트가 필수라는 점을 다시 한 번 느꼈습니다. 운영 배포 전 개발 서버에서 발견되어서 정말 다행이라고 생각합니다.
지금 환경에서는 온프레미스를 항상 고려해야 하기 때문에 앞으로 새로운 패키지를 추가할 때는
• UMD/Min 등 단일 번들 형태를 우선 도입해 경로 의존성 충돌을 최대한 방지하고 필요 시 rollup·webpack·esbuild 등을 통해 ESM 형태로 전환한 뒤 내부 환경에서 실제로 CJS/EJS가 어떻게 감지되는지 꼼꼼히 확인하는 과정을 거치는 것이 좋겠습니다.