Vue 3.0/05.vuerouter

[vue3-router] 07. 지연 로딩 경로

  • -

이번 포스트에서는 lazy loading route 즉 지연 로딩 경로라는 것에 대해서 알아보자.

lazy loading route

 

우리는 SPA

Vue의 큰 특징은 SPA 즉 Single Page Application이다. 이녀석은 "최초 사이트에 요청 시 전체 애플리케이션에 대한 내용을 가져오고 이후에는 데이터만 이동하기 때문에 매우 효율적이다"라고 학습한 적이 있다.

https://goodteacher.tistory.com/545

 

[vue 3] 01.SPA & SFC & Vite

이번 포스트에서는 SPA와 SFC 그리고 이를 구현하기 위한 Vite에 대해서 살펴보자. SPA vs MPA 정의 SPA(Single Page Application)과 MPA(Multi Page Application)이라는 용어에 대해서 살펴보자. 말 그대로 애플리케이

goodteacher.tistory.com

 

그런데 "만약 우리의 앱이 (그럴리는 없겠지만) 100만개의 화면으로 이루어져있다면 어떨까? 이 컴포넌트들을 한번에 받으려면 서버에 얼마나 많은 부하를 줄까? 그리고 그렇게 힘들게 받아온 컴포넌트들이 과연 처음부터 다 필요할까?" 라는 질문을 던질 수 있다면 laxy loading route에 대해서 고민해볼 필요가 있다.

 

lazy loading routes

지연 로딩 경로란 말 그대로 앱을 시작하자 마자 로딩하지 않고 최대한 게으르게 있다가 필요해지면 그때 로딩하는 것을 말한다. 

Vue Router에서 객체를 가져오는 방법은 정적 로딩과 동적 로딩이 있다. 기본으로 제공되는 router의 index.js를 살펴보자.

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'            // 정적 로딩

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      component: () => import('../views/AboutView.vue') // 동적 로딩
    }
  ]
})

export default router

먼저 HomeView처럼 사용하는 것이 정적 로딩이고 AboutView에 있는 것처럼 import 함수 형태로 로딩하는 것을 동적 로딩이라고 한다. 일단 AboutView.vue를 정적 로딩으로 변경해서 앱을 실행해보자.

 

그럼 아래와 같은 화면이 실행되는데 기본적으로 App.vue가 있고 RouterView에 HomeView의 내용이 출력된다. AboutView는 아직 출력되고 있지는 않기 때문에 사실상 필요하지는 않다.

하지만 개발자도구의 네트워크 탭을 살펴보면 앱을 실행하면서 모든 vue들을 다 요청해서 받고 있음을 알 수 있다.( /.vue$/로 filtering 한 상태)

지금은 불필요한 AboutView 다운에 2.4kb, 12ms나 소모하다니!!

아직은 AboutView가 필요 없지만 2.4kb나 되는 녀석을 12ms에 걸쳐 받은 것이다. (시간은 상황에 따라 차이가 많이 난다.)물론 AboutView를 클릭하면 새롭게 받아오지는 않지만 초기에 많은 자원을 낭비한 것은 틀림없는 사실이다. 이제 다시 AboutView를 초기 모습인 동적 로딩으로 변경 후 테스트 해보자.

 

이제는 AboutView를 초기에 로딩하지 않은 것을 확인할 수 있다. 그리고 About 링크를 클릭하면 비로소 AboutView를 다운로드 한다. 이처럼 동적 로딩 기반의 lazy loading routes를 사용하면 필요한 때 효율적으로 리소스를 활용할 수 있다.

 

 

동일한 chunk(덩어리)에 컴포넌트 그룹화

 

필요성

lazy loading route를 구성하는 컴포넌트들을 시나리오에 따라 하나의 chunk(파일)로 그룹화 해서 다운로드 할 수 있다. 잔펀치로 하나씩 하나씩 하는 것 보다는 한덩어리씩 가져오는 것이 훨씬 효율적이다.

이 과정은 개발 단계의 이야기는 아니고 production 레벨의 이야기 이다. 따라서 build 과정에 설정이 필요하다. 작성된 app을 build 해보자.

 

만약 모든 경로를 정적으로 처리했다면 다음과 같은 빌드 결과가 나온다.

index.js에 모든 내용이 포함된다.

 

즉 모든 component 정보들은 index-[hash].js chunk 하나에 통합되고 이 하나가 다운로드 된다.(js만 이야기 한다)

만약 AboutView를 lazy loading 처리하고 build 해보면 별도의 chunk로 생성된다. 즉 AboutView-[hash].js가 별도로 분리되서 관리되는 것이다. 이처럼 lazy loading을 처리하면 따로따로 파일이 분리되고 잔펀치가 나가게 된다.  ThirdView.vue를 경로에 lazy loading으로 등록하고 확인해보자.

lazy loading 하나당 하나의 chunk가 생성된다.

 

동적 로딩 경로가 많아지면 많아질 수록 파일들도 쪼개지기 때문에 그룹화가 필요해진다.

 

그룹화 처리

그룹화를 처리하기 위해서는 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로 묶인다.

크게 lazyloading, index, modules 3개의 chunk로 분해된 모습

이제 AboutView나 ThirdView가 필요한 시점에 lazyloading-[hash].js가 다운로드 되서 서비스가 가능해졌다.

 

manualChunks는 이전에는(Vue router 공식 문서에도) 배열 형태로도 설정할 수 있었지만 vite 최근 버전에서는 함수 형태만 지원하고 있다. https://rollupjs.org/configuration-options/#output-manualchunks

 

rollup-plugin-visualizer

 

rollup-plugin-visualizer

이 라이브러리는 프로젝트 빌드 결과 파일들이 얼마나 용량을 차지하는지 보여주는 신기한 녀석이다. 간단히 설치하고 사용해보자.

먼저 설치는 npm 사이트를 참조한다.

https://www.npmjs.com/package/rollup-plugin-visualizer

 

rollup-plugin-visualizer

[![NPM Version](https://img.shields.io/npm/v/rollup-plugin-visualizer.svg)](https://npmjs.org/package/rollup-plugin-visualizer) [![Node.js CI](https://github.com/btd/rollup-plugin-visualizer/actions/workflows/node.js.yml/badge.svg)](https://github.com/btd.

www.npmjs.com

 

그리고 vite.config.js 파일에 다음과 같이 visualizer 플러그인을 설정한다.

import { visualizer } from "rollup-plugin-visualizer";

export default defineConfig({
  plugins: [
    vue(),
    visualizer({
      filename: "./dist/report.html",
      open: true,
      brotliSize: true,
    }),
  ],
  ...
  });

이제 평소처럼 build를 실행하면 자동으로 아래와 같은 분석 결과를 출력해준다.

신기하다.

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.