Angular에서 경로 수준 코드 분할

경로 수준 코드 분할을 사용하여 앱 성능을 개선하세요.

이 게시물에서는 Angular 애플리케이션에서 경로 수준 코드 분할을 설정하는 방법을 설명합니다. 이렇게 하면 JavaScript 번들 크기를 줄이고 상호작용까지의 시간을 크게 개선할 수 있습니다.

이 도움말의 코드 샘플은 GitHub에서 확인할 수 있습니다. 즉시 라우팅 예시는 eager 브랜치에서 확인할 수 있습니다. 경로 수준 코드 분할 예는 지연 브랜치에 있습니다.

코드 분할이 중요한 이유

웹 애플리케이션이 점점 더 복잡해짐에 따라 사용자에게 제공되는 JavaScript의 양이 크게 증가했습니다. 대용량 자바스크립트 파일은 상호작용을 현저하게 지연시킬 수 있으므로, 특히 모바일에서 리소스가 많이 사용될 수 있습니다.

애플리케이션의 기능을 그대로 유지하면서 JavaScript 번들을 축소하는 가장 효율적인 방법은 적극적인 코드 분할을 도입하는 것입니다.

코드 분할을 사용하면 애플리케이션의 JavaScript를 다양한 경로 또는 기능과 연결된 여러 청크로 분할할 수 있습니다. 이 접근 방식은 초기 애플리케이션을 로드하는 동안 사용자에게 필요한 JavaScript만 전송하여 로드 시간을 짧게 유지합니다.

코드 분할 기법

코드 분할은 구성요소 수준경로 수준의 두 가지 수준에서 수행할 수 있습니다.

  • 구성요소 수준의 코드 분할에서는 구성요소를 자체 자바스크립트 청크로 이동하고 필요할 때 느리게 로드합니다.
  • 경로 수준 코드 분할에서는 각 경로의 기능을 별도의 청크로 캡슐화합니다. 사용자는 애플리케이션을 탐색할 때 개별 경로와 연결된 청크를 가져오고 필요할 때 관련 기능을 가져옵니다.

이 게시물에서는 Angular에서 경로 수준 분할을 설정하는 방법을 중점적으로 설명합니다.

샘플 애플리케이션

Angular에서 경로 수준 코드 분할을 사용하는 방법을 알아보기 전에 샘플 앱을 살펴보겠습니다.

앱 모듈의 구현을 확인하세요. AppModule 내에는 두 개의 경로, 즉 HomeComponent와 연결된 기본 경로와 NyanComponent와 연결된 nyan 경로가 정의됩니다.

@NgModule({
  ...
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: '',
        component: HomeComponent,
        pathMatch: 'full'
      },
      {
        path: 'nyan',
        component: NyanComponent
      }
    ])
  ],
  ...
})
export class AppModule {}

경로 수준 코드 분할

코드 분할을 설정하려면 nyan 즉시 경로를 리팩터링해야 합니다.

Angular CLI 버전 8.1.0은 다음 명령어를 사용하여 모든 작업을 수행할 수 있습니다.

ng g module nyan --module app --route nyan

그러면 다음이 생성됩니다. - NyanModule라는 새 라우팅 모듈 - NyanModule를 동적으로 로드하는 nyan이라는 AppModule의 경로 - NyanModule의 기본 경로 - 사용자가 기본 경로에 도달할 때 렌더링되는 NyanComponent라는 구성요소

Angular로 코드 분할을 구현하는 방법을 더 잘 이해할 수 있도록 이 단계를 수동으로 진행해 보겠습니다.

사용자가 nyan 경로로 이동하면 라우터는 라우터 콘센트에서 NyanComponent를 렌더링합니다.

Angular에서 경로 수준 코드 분할을 사용하려면 경로 선언의 loadChildren 속성을 설정하고 동적 가져오기와 결합합니다.

{
  path: 'nyan',
  loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}

Eager 경로와는 두 가지 주요 차이점이 있습니다.

  1. component 대신 loadChildren를 설정합니다. 경로 수준 코드 분할을 사용할 때는 구성요소가 아닌 동적으로 로드된 모듈을 가리켜야 합니다.
  2. loadChildren에서 프로미스가 해결되면 NyanComponent를 가리키는 대신 NyanModule를 반환합니다.

위의 스니펫은 사용자가 nyan로 이동할 때 Angular가 nyan 디렉터리에서 nyan.module를 동적으로 로드하고 모듈에 선언된 기본 경로와 연결된 구성요소를 렌더링해야 한다고 지정합니다.

다음 선언을 사용하여 기본 경로를 구성요소와 연결할 수 있습니다.

import { NgModule } from '@angular/core';
import { NyanComponent } from './nyan.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [NyanComponent],
  imports: [
    RouterModule.forChild([{
      path: '',
      pathMatch: 'full',
      component: NyanComponent
    }])
  ]
})
export class NyanModule {}

이 코드는 사용자가 https://example.com/nyan로 이동할 때 NyanComponent를 렌더링합니다.

Angular 라우터가 로컬 환경에서 nyan.module를 느리게 다운로드하는지 확인하려면 다음 안내를 따르세요.

  1. `Control+Shift+J` (Mac에서는 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  2. 네트워크 탭을 클릭합니다.

  3. 샘플 앱에서 NYAN을 클릭합니다.

  4. nyan-nyan-module.js 파일이 네트워크 탭에 표시됩니다.

경로 수준 코드 분할로 JavaScript 번들의 지연 로드

GitHub에서 이 예를 찾아보세요.

스피너 표시

지금은 사용자가 NYAN 버튼을 클릭해도 애플리케이션이 백그라운드에서 JavaScript를 로드하고 있다고 표시하지 않습니다. 스크립트를 로드하는 동안 사용자에게 피드백을 제공하려면 스피너를 추가하는 것이 좋습니다.

이렇게 하려면 먼저 app.component.htmlrouter-outlet 요소 내부에 표시기의 마크업을 추가합니다.

<router-outlet>
  <span class="loader" *ngIf="loading"></span>
</router-outlet>

그런 다음 라우팅 이벤트를 처리하는 AppComponent 클래스를 추가합니다. 이 클래스는 RouteConfigLoadStart 이벤트를 수신하면 loading 플래그를 true로 설정하고 RouteConfigLoadEnd 이벤트를 수신하면 플래그를 false로 설정합니다.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  loading: boolean;
  constructor(router: Router) {
    this.loading = false;
    router.events.subscribe(
      (event: RouterEvent): void => {
        if (event instanceof NavigationStart) {
          this.loading = true;
        } else if (event instanceof NavigationEnd) {
          this.loading = false;
        }
      }
    );
  }
}

아래 예에서는 실제 스피너를 볼 수 있도록 인위적인 500ms 지연 시간을 도입했습니다.

결론

경로 수준 코드 분할을 적용하여 Angular 애플리케이션의 번들 크기를 줄일 수 있습니다.

  1. Angular CLI 지연 로드 모듈 생성기를 사용하여 동적으로 로드된 경로를 자동으로 스캐폴드합니다.
  2. 사용자가 지연 경로로 이동할 때 진행 중인 작업이 있음을 표시하기 위해 로드 표시기를 추가합니다.