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

가상 스크롤을 구현하여 큰 목록의 응답성을 개선합니다.

Stephen Fluin
Stephen Fluin

스크롤 목록은 자주 사용하는 소셜 미디어 사이트에서 무한 스크롤되는 피드를 탐색하든 기업 대시보드를 탐색하든 오늘날 가장 일반적인 UI 패턴 중 하나입니다. 스크롤 목록이 매우 길어지면 (수백 개, 수천 개, 수십만 개) 애플리케이션 성능이 저하될 수 있습니다.

애플리케이션이 모든 데이터를 미리 로드하고 렌더링해야 하므로 큰 목록은 로드 속도가 느려질 수 있습니다. 또한 목록의 각 항목에 리치 데이터 , 미디어 및 기능이 포함되어 있을 수 있으므로 렌더링과 탐색 속도가 느려질 수 있습니다.

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

Component Dev Kit를 사용한 Angular의 가상 스크롤

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

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

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

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

가상 스크롤 설정

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

npm install --save @angular/cdk

앱에 ScrollingModule 추가

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

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);
}

브라우저가 앱을 렌더링할 때 100,000개의 개별 <div> 요소를 렌더링해야 합니다. 간단한 텍스트 노드에는 이 방법이 문제가 될 수 있지만 반복되는 템플릿의 복잡성은 제대로 확장되지 않으며 모든 이벤트 리스너가 크게 곱해집니다.

가상 스크롤을 추가하고 이러한 문제를 방지하려면 목록을 <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 / Fbien Barral의 히어로 이미지