React.lazy와 청크 오류: 배포 후 갇힌 사용자 복구 방법

발행: (2026년 5월 25일 AM 01:11 GMT+9)
3 분 소요
원문: Dev.to

출처: Dev.to

클래식한 React 프로덕션 버그: 새로운 번들을 배포했는데 사용자는 탭에 오래된 HTML을 캐시하고 있고, 라우트로 이동하면 → React.lazy()가 더 이상 CDN에 존재하지 않는 청크를 가져오려고 시도 → 화면이 빈칸이 됩니다.
https://cdn.example.com/assets/Page-abc123.js
사용자는 강제 새로고침 외에 탈출구가 없으며, 대부분은 그 방법을 모릅니다.

청크 로드 오류를 잡아내고 캐시 무효화 파라미터와 함께 페이지를 강제 새로고침하는 전역 오류 리스너:

const CHUNK_ERROR_PATTERNS = [
  /Loading chunk \d+ failed/i,
  /Failed to fetch dynamically imported module/i,
  /Loading CSS chunk .* failed/i,
  /Importing a module script failed/i,
];
window.addEventListener('error', (e) => {
  const msg = e?.message || '';
  if (CHUNK_ERROR_PATTERNS.some(rx => rx.test(msg))) {
    const url = new URL(window.location.href);
    url.searchParams.set('_r', String(Date.now()));
    window.location.replace(url.toString());
  }
});

각 부분이 중요한 이유:

  • 여러 패턴: 브라우저마다 다른 메시지를 던집니다. Safari는 "Importing a module script failed"를, Chrome은 "Failed to fetch dynamically imported module"을, 오래된 Webpack 빌드는 "Loading chunk N failed"를 사용합니다.
  • 대소문자 구분 없음: 일부 브라우저는 대문자를, 일부는 소문자를 사용합니다.
  • 캐시 무효화 파라미터: ?_r=를 추가하면 새로운 index.html을 강제로 받아오게 되며, 여기에는 새로운 청크 해시가 포함됩니다.
  • replace()assign()이 아닌 이유: 히스토리 항목을 추가하지 않으므로 뒤로 가기 버튼이 정상 작동합니다.

주의사항

  • lazy import가 프로미스 내부에서 오류를 발생시키면 unhandledrejection도 잡히므로, 누락되는 경우 두 번째 리스너를 추가하세요.
  • 네트워크 장애 시 무한 루프에 빠지지 않도록 한 번만 새로고침하도록 플래그를 두세요.
  • 테스트 방법: 새 빌드를 배포하고, 오래된 탭을 열어 라우트 이동을 시도하면 자동으로 복구되는지 확인합니다.

15줄 정도의 코드지만, 배포 후 앱을 포기하는 사용자를 실제로 상당히 줄여줍니다.

0 조회
Back to Blog

관련 글

더 보기 »

내 스킬

프로젝트를 위한 AI 지시문을 만들고, 설치하고, 관리하세요 — 코딩이 필요 없습니다. CREATE 이름을 정하고, 카테고리를 선택하고, 원하는 것을 설명하세요 — 마법사가 자동으로 구성합니다.