PDF.js 배포시 worker 파일 mjs와 js 차이

rabyeoljji·2025년 3월 15일

techblog (기술블로그)

목록 보기
15/17
post-thumbnail


트러블 상황

next.js 프로젝트를 진행 중, pdfjs를 이용한 파일 처리 기능을 구현했는데, 로컬에서는 정상적으로 worker가 동작하는데 배포서비스에서는 동작하지 않는 현상이 발생했다.

pdfjs 버전도 변경해보고, cmap url도 다르게 지정해보고 해봤지만 해결이 안됐다.

하지만 이 문제가 worker의 문제라는 걸 알게 되었고, worker가 동작해야 파일 처리가 가능한데 pdf worker파일을 public 하위에 pdf.worker.min.mjs로 둔 상황에서 이 mjs 확장자가 배포 시에는 불안정하게 동작할 수 있다는 정보를 접하게 되었다.

.mjs ⇒ .js로 변경하자 정상 작동하게 되었다.




💡생각해보니 mjs와 js 확장자의 차이를 제대로 공부해본 적이 없었음, 이 기회에 정리해보자!



📌 .mjs vs .js 차이점


1️⃣ .mjs (ES 모듈, ECMAScript Module)

  • ES6(ES2015)에서 도입된 모듈 시스템(ESM, ECMAScript Module) 방식
  • import / export 키워드를 사용하여 모듈을 가져옴
  • 브라우저와 최신 Node.js 환경에서 기본 지원됨
  • .mjs 확장자가 붙어 있으면 자동으로 ESM(ECMAScript Module)으로 인식됨

📌 .mjs 예제 (ESM 방식)

// math.mjs
export function add(a, b) {
  return a + b;
}
// main.mjs
import { add } from "./math.mjs";
console.log(add(2, 3)); // 5

2️⃣ .js (기본적으로 CommonJS, 하지만 ESM도 가능)

  • 기본적으로 CommonJS 방식 (require, module.exports)
  • Node.js에서는 기본적으로 .js 파일을 CommonJS로 해석
  • 하지만 package.json에서 "type": "module"을 설정하면 .js도 ESM처럼 동작할 수 있음
  • 브라우저에서는 여전히 <script type="module">을 사용하면 ESM 방식으로 인식

📌 .js 예제 (CommonJS 방식)

// math.js (CommonJS)
function add(a, b) {
  return a + b;
}
module.exports = { add };
// main.js (CommonJS)
const { add } = require("./math.js");
console.log(add(2, 3)); // 5



📌 왜 .mjs가 배포 환경에서 문제를 일으켰을까?

💡 주요 원인은 서버의 MIME 타입과 모듈 시스템 차이 때문!


1️⃣ 서버가 .mjs를 올바르게 처리하지 못했을 가능성

  • 대부분의 웹 서버(예: Nginx, Apache, Next.js)는 .jsapplication/javascript으로 인식
  • 하지만 .mjs는 일부 서버에서 application/octet-stream(일반 바이너리 파일)로 처리될 수도 있음⭐
  • 브라우저가 application/javascript가 아닌 MIME 타입을 받으면 실행을 차단

2️⃣ Next.js나 Webpack이 .mjs를 제대로 처리하지 못했을 가능성

  • Next.js는 기본적으로 .mjs 파일을 ES 모듈로 해석
  • 하지만 pdf.worker.min.mjs는 브라우저에서 Web Worker로 실행되므로, ESM으로 불러오면 import 관련 에러가 날 수도 있음
  • .js로 변경하면 CommonJS 방식으로 로드되기 때문에 문제가 해결됨

3️⃣ PDF.js에서 Web Worker를 불러오는 방식과 충돌 가능성

  • PDF.js의 workerSrc는 내부적으로 <script> 태그를 생성해서 로드
  • .mjs 파일을 ESM 방식으로 불러오려면 <script type="module">로 로드해야 하지만, PDF.js는 그렇게 처리하지 않음
  • 따라서 .js로 변경하면 기존 방식 그대로 로드할 수 있어서 정상 작동



🚀 결론: .mjs.js를 언제 써야 할까?

구분.mjs (ESM).js (CommonJS or ESM)
Node.js 기본 모드❌ (해석 불가)✅ (CommonJS)
Node.js에서 type: "module" 설정✅ (ESM 모드)✅ (ESM 모드)
브라우저 실행✅ (<script type="module">)✅ (<script> 기본 실행)
PDF.js Web Worker⚠️ (충돌 가능)✅ (정상 작동)
Next.js 환경⚠️ (Webpack 처리 문제 발생 가능)✅ (안정적)
profile
⛅🛩️ 먼 길을 돌아서 온 프론트엔드 개발자 ✈️⛅

0개의 댓글