만족

[React] ChunkLoadError: Loading chunk N failed. 본문

[React] ChunkLoadError: Loading chunk N failed.

FrontEnd/React Satisfaction 2021. 3. 9. 19:25

satisfactoryplace.tistory.com/93?category=829221

 

[React] 프로덕션 최적화: 코드 스플리팅

create-react-app 으로 리액트 프로젝트를 생성했다면 프로젝트 빌드 시에 webpack을 이용해 많은 파일들을 큰 몇개의 덩어리로 합쳐준다. webpack은 SPA(Single Page Application)을 제작하기에 제격인 빌드 도..

satisfactoryplace.tistory.com

 

코드 스플리팅을 한 이후 이 에러를 만날 수 있다.

https://cpsp.kr/players/ (v 1.0.2)
ChunkLoadError: Loading chunk 3 failed.
(error: https://cpsp.kr/static/js/3.62522664.chunk.js)
Loading chunk 3 failed.
(error: https://cpsp.kr/static/js/3.62522664.chunk.js)

먼저 이 오류가 왜 발생하는지를 알아보자.

 

첫 번째 배포 후 프로덕션은 다음과 같은 구조로 이루어져 있다.

 

 

첫 배포 후 상태

그런데, 업데이트 등의 이유로 새로 빌드하고 난 후에는 다음과 같이 변한다

 

업데이트 배포 후 상태

문제는 여기서 발생한다.

 

A,B,C 청크는 삭제되고 업데이트된 Main.js에서는 D,E,F 청크를 사용하는데,

 

모종의 이유(캐시되었거나, 이전 버전에서 창을 닫지 않은 상태 등)로

이전 버전의 main.js를 사용하는 클라이언트는 여전히 A,B,C 청크를 로드하려 한다.

 

그러면 당연히 서버에는 A,B,C 청크는 존재하지 않으므로, ChunkLoadError 가 발생하는 것이다.

 

해결법

첫 번째 해결법으로는, package.json에 명시한 version 정보를 검사하는 방법이 있다.

{ "homepage": "/", "version": "1.1.0", ... }

package.json에서 version값을 가져오는 방법은 아래의 포스트를 참조하라.

satisfactoryplace.tistory.com/166?category=829221

 

[React] package.json으로부터 version 가져오기

오류 로깅이나, 버그 접수 시 사용중인 버전 정보 확인이 필요하다. 그래서 package.json을 임포트하여 version값을 뽑아오려 했으나 오류가 발생한다. package.json은 프로젝트 루트 위치(src보다 상위 레

satisfactoryplace.tistory.com

서버에 최신 버전에 대한 정보를 리턴하는 api를 만들어, 최신 버전인지 검사하고

최신 버전이 아니면 아래 코드를 이용해 캐시를 무시하고 새로고침한다.

window.reload(true);

간단하지만 별도의 백엔드 서버를 구축하지 않았다면 다른 방법을 사용해야 한다.

 

두 번째 방법으로는, 방문 시 무조건 한번은 캐시를 무시하게 만드는 방법이다.

 

const random= Math.random();
const urlParams= new URLSearchParams(location.search);
if(!urlParams.refreshed){
	//첫 방문 시 임의의 쿼리 파라미터를 줘서 캐시 무시
	window.location= `.?refreshed=${random}`;
}

 

이 방법은 간단하지만 별로 추천하지 않는다.

 

첫 로딩까지 걸리는 시간이 배로 들기 때문에 전환율을 떨어뜨릴 위험이 있기 때문이다.

 

세 번째 방법으로는, Splited Component에 대해 Error Boundary를 사용하는 방법이 있다.

 

ko.reactjs.org/docs/code-splitting.html

 

코드 분할 – React

A JavaScript library for building user interfaces

ko.reactjs.org

리액트 공식 문서에서도 설명하고 있듯이, 레이지 로딩을 사용하는 코드를 ErrorBoundary로 감싸서 청크 로딩 실패 여부를 해당 바운더리에서 감지한다.

 

주의할 점은 반드시 Lazy-loaded Component에서 반드시 ErrorBoundary를 별도로 설정해줘야 한다는 점이다.

//OtherComponent.js

const OtherComponent= ()=>{
  //CustomErrorBoundary에서는 ChunkLoadError를 제외한 모든 예외가 처리될 것이다.
  return (<CustomErrorBoundary>
      <MaybeErrorOccur/>
    </CustomErrorBoundary>);
}

//
export default OtherComponent;

 

그렇지 않으면, 해당 오류가 아닌 에러 발생시에도 전부 MyErrorBoundary에서 걸리게 되어, 바운더리 코드 자체가 지저분해질 수 있다.

 

또한, 네트워크에 연결되어 있는지, 서버 자체가 다운된 것은 아닌지도 확인해야 한다.

 

청크 로드 실패의 원인에는 위에서 말한 경우도 있겠지만 네트워크 연결이 원활하지 않거나, 서버가 다운된 경우에도 실패하기 때문에,

무턱대고 MyErrorBoundary에서 window.reload(true) 등을 사용한다면 사용자는 무한 루프에 빠지게 된다는 점을 명심하자.

 

window.navigator.onLine //true== connected, false == disconnected

네트워크 연결 여부는 위의 코드를 통해 확인할 수 있고

서버 다운 여부는 사용중인 서버에 임의의 요청을 보낸 후 정상적으로 리턴되는지를 확인하면 되겠다.

 



Comments