그런데 "만약 우리의 앱이 (그럴리는 없겠지만) 100만개의 화면으로 이루어져있다면 어떨까? 이 컴포넌트들을 한번에 받으려면 서버에 얼마나 많은 부하를 줄까? 그리고 그렇게 힘들게 받아온 컴포넌트들이 과연 처음부터 다 필요할까?" 라는 질문을 던질 수 있다면 laxy loading route에 대해서 고민해볼 필요가 있다.
lazy loading routes
지연 로딩 경로란 말 그대로 앱을 시작하자 마자 로딩하지 않고 최대한 게으르게 있다가 필요해지면 그때 로딩하는 것을 말한다.
Vue Router에서 객체를 가져오는 방법은 정적 로딩과 동적 로딩이 있다. 기본으로 제공되는 router의 index.js를 살펴보자.
먼저 HomeView처럼 사용하는 것이 정적 로딩이고 AboutView에 있는 것처럼 import 함수 형태로 로딩하는 것을 동적 로딩이라고 한다. 일단 AboutView.vue를 정적 로딩으로 변경해서 앱을 실행해보자.
그럼 아래와 같은 화면이 실행되는데 기본적으로 App.vue가 있고 RouterView에 HomeView의 내용이 출력된다. AboutView는 아직 출력되고 있지는 않기 때문에 사실상 필요하지는 않다.
하지만 개발자도구의 네트워크 탭을 살펴보면 앱을 실행하면서 모든 vue들을 다 요청해서 받고 있음을 알 수 있다.( /.vue$/로 filtering 한 상태)
아직은 AboutView가 필요 없지만 2.4kb나 되는 녀석을 12ms에 걸쳐 받은 것이다. (시간은 상황에 따라 차이가 많이 난다.)물론 AboutView를 클릭하면 새롭게 받아오지는 않지만 초기에 많은 자원을 낭비한 것은 틀림없는 사실이다. 이제 다시 AboutView를 초기 모습인 동적 로딩으로 변경 후 테스트 해보자.
이제는 AboutView를 초기에 로딩하지 않은 것을 확인할 수 있다. 그리고 About 링크를 클릭하면 비로소 AboutView를 다운로드 한다. 이처럼 동적 로딩 기반의 lazy loading routes를 사용하면 필요한 때 효율적으로 리소스를 활용할 수 있다.
동일한 chunk(덩어리)에 컴포넌트 그룹화
필요성
lazy loading route를 구성하는 컴포넌트들을 시나리오에 따라 하나의 chunk(파일)로 그룹화 해서 다운로드 할 수 있다. 잔펀치로 하나씩 하나씩 하는 것 보다는 한덩어리씩 가져오는 것이 훨씬 효율적이다.
이 과정은 개발 단계의 이야기는 아니고 production 레벨의 이야기 이다. 따라서 build 과정에 설정이 필요하다. 작성된 app을 build 해보자.
만약 모든 경로를 정적으로 처리했다면 다음과 같은 빌드 결과가 나온다.
즉 모든 component 정보들은 index-[hash].js chunk 하나에 통합되고 이 하나가 다운로드 된다.(js만 이야기 한다)
만약 AboutView를 lazy loading 처리하고 build 해보면 별도의 chunk로 생성된다. 즉 AboutView-[hash].js가 별도로 분리되서 관리되는 것이다. 이처럼 lazy loading을 처리하면 따로따로 파일이 분리되고 잔펀치가 나가게 된다. ThirdView.vue를 경로에 lazy loading으로 등록하고 확인해보자.
동적 로딩 경로가 많아지면 많아질 수록 파일들도 쪼개지기 때문에 그룹화가 필요해진다.
그룹화 처리
그룹화를 처리하기 위해서는 vite.config.js 파일에서 defineConfig의 옵션 객체에 아래 내용을 추가한다.
build: {
rollupOptions: {
output: {
// 함수 형태로만 지원되며 id는 파일의 이름
manualChunks(id){
if (id.includes('node_modules')) {
return 'moduls';
}else if(id.includes('AboutView') || id.includes("ThirdView")){
console.log("manual chunk id: ", id)
return 'lazyloading'
}
}
},
},
},
manualChunks에는 id가 전달되는데 id는 파일의 이름(경로포함)이다. 그래서 현재는 node_modules가 포함되면 moduls chunk로, AboutView, ThirdView가 포함되면 lazyloading chunk로 그룹화 시킨다. 이외의 내용들은 평소처럼 index chunk로 묶인다.
이제 AboutView나 ThirdView가 필요한 시점에 lazyloading-[hash].js가 다운로드 되서 서비스가 가능해졌다.
manualChunks는 이전에는(Vue router 공식 문서에도) 배열 형태로도 설정할 수 있었지만 vite 최근 버전에서는 함수 형태만 지원하고 있다. https://rollupjs.org/configuration-options/#output-manualchunks
rollup-plugin-visualizer
rollup-plugin-visualizer
이 라이브러리는 프로젝트 빌드 결과 파일들이 얼마나 용량을 차지하는지 보여주는 신기한 녀석이다. 간단히 설치하고 사용해보자.