Angular CDK를 사용하여 대규모 목록 가상화

가상 스크롤을 구현하여 대규모 목록의 반응성을 개선하세요.

Stephen Fluin
Stephen Fluin

스크롤 목록은 좋아하는 소셜 미디어 사이트에서 무한 스크롤 피드를 탐색하거나 엔터프라이즈 대시보드를 탐색하는 등 오늘날 가장 일반적인 UI 패턴 중 하나입니다. 스크롤 목록이 매우 길어지면(수백, 수천, 수십만 개의 항목) 애플리케이션 성능이 저하될 수 있습니다.

애플리케이션에서 모든 데이터를 미리 로드하고 렌더링해야 하므로 대규모 목록은 로드 속도가 느릴 수 있습니다. 또한 목록의 각 항목에 풍부한 데이터, 미디어, 기능이 포함될 수 있으므로 렌더링 및 탐색 속도가 느릴 수 있습니다.

사용자가 페이지를 로드하거나 스크롤할 때 문제가 발생하여 불만을 느끼고 페이지를 중단할 수 있습니다.

구성요소 개발자 키트를 사용한 Angular의 가상 스크롤

가상 스크롤은 이러한 크기 조정 문제를 해결하는 데 사용되는 기본 기술입니다. 가상 스크롤은 적절한 크기의 스크롤바를 제공하여 매우 큰 목록의 인상을 줄 수 있으며, 애플리케이션이 전체 목록을 메모리에 보관하거나 페이지에서 렌더링하지 않고도 목록을 탐색할 수 있습니다.

Angular에서 가상 스크롤은 Component Dev Kit (CDK)를 통해 제공됩니다. 목록을 반복하는 방식을 수정하고 몇 가지 구성 매개변수를 추가로 제공하면 CDK의 가상 스크롤이 목록의 가상 렌더링을 자동으로 관리하여 페이지 성능과 응답성을 개선합니다.

한 번에 전체 목록을 렌더링하는 대신 화면에 맞는 항목의 하위 집합과 작은 버퍼만 렌더링됩니다. 사용자가 탐색하면 새 하위 집합의 항목이 계산되고 렌더링되며 원하는 경우 기존 DOM을 재사용합니다.

이 게시물의 나머지 부분에서는 기본 가상 스크롤을 설정하는 방법을 안내합니다. 이 샘플 앱에서 작동하는 전체 예시를 확인할 수 있습니다.

가상 스크롤 설정

먼저 좋아하는 패키지 관리자를 사용하여 @angular/cdk를 설치했는지 확인합니다. npm을 사용하여 설치하려면 터미널에서 다음 명령어를 실행합니다.

npm install --save @angular/cdk

앱에 ScrollingModule 추가

CDK가 설치된 상태에서 @angular/cdk/scrolling 패키지에서 가상 스크롤을 처리하는 ScrollingModule를 가져옵니다. 그런 다음 모듈의 가져오기 배열에 추가합니다.

import {ScrollingModule} from '@angular/cdk/scrolling';

...
imports: [
  ScrollingModule
...
]
...

뷰포트 만들기

패키지가 작동하는 방식을 확인하려면 0~99,999 사이의 간단한 숫자 목록으로 구성요소를 만들어 보세요.

@Component({
  template: `<div *ngFor="let item of list">{{item}}</div>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

브라우저가 앱을 렌더링할 때는 개별 <div> 요소 10만 개를 렌더링해야 합니다. 이는 간단한 텍스트 노드에는 적합할 수 있지만 반복되는 템플릿의 복잡성은 확장되지 않으며 이벤트 리스너가 크게 늘어납니다.

가상 스크롤을 추가하고 이러한 문제를 방지하려면 목록을 <cdk-virtual-scroll-viewport> 요소로 래핑하여 뷰포트를 만들어야 합니다.

@Component({
  template: `<cdk-virtual-scroll-viewport>
    <div *ngFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

ScrollingModule는 목록의 하위 집합을 동적으로 렌더링하므로 표준 CSS를 통해 표시 영역의 높이를 지정해야 합니다. 또한 itemSize를 지정하여 뷰포트에 콘텐츠에 관한 힌트를 제공해야 합니다. 모듈은 이 정보를 사용하여 지정된 시간에 DOM에 유지할 항목 수와 적절한 크기의 스크롤바를 렌더링하는 방법을 결정합니다.

@Component({
  template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
    <div *ngFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

마지막으로 *ngFor*cdkVirtualFor로 변환합니다.

@Component({
  template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
    <div *cdkVirtualFor="let item of list">{{item}}</div>
    </cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
  list = Array.from({length: 100000}).map((_, i) => i);
}

전체 목록을 반복하는 대신 표시 영역이 사용자를 위해 목록의 올바른 하위 집합을 동적으로 식별하고 반복합니다. 이제 사용자가 페이지를 로드하면 CDK가 화면에 맞는 목록의 하위 집합(및 약간의 버퍼)을 렌더링해야 하며, 뷰포트의 모든 스크롤 이벤트는 목록의 적절한 하위 집합을 로드하고 렌더링합니다.

사용자가 스크롤할 때 목록의 CDK 렌더링 하위 집합입니다.

추가 정보

CDK의 가상 스크롤 기능은 이 기본 예시보다 훨씬 더 많은 기능을 제공합니다. 샘플 앱에서는 전체 목록이 메모리에 있었지만, 더 복잡한 애플리케이션의 경우 목록을 필요에 따라 가져올 수 있습니다. ScrollingModulecdkVirtualOf 디렉티브의 다른 기능에 대한 자세한 내용은 CDK 문서에서 Scrolling에 관해 알아보세요.

Unsplash의 Mr Cup/Fabien Barral님 제공 히어로 이미지