뛰어난 웹 프레임워크인 AnglarJS는 프런트엔드 개발 부담을 크게 단순화할 수 있습니다. Sebastian Fröstl은 최근 블로그 게시물 "긴 목록을 위한 AngularJS 성능 조정"에서 복잡한 데이터 구조가 포함된 대규모 목록을 처리할 때 AnglarJS가 매우 느리게 실행된다고 밝혔습니다. 그는 또한 기사에서 해결책을 공유했습니다. 아래는 기사 번역입니다.
AnglarJS는 훌륭하지만 복잡한 데이터 구조가 포함된 대규모 목록을 처리할 때 매우 느리게 실행됩니다. 이는 핵심 관리 페이지를 AngularJS로 마이그레이션하는 동안 발생한 문제입니다. 이 페이지는 500행의 데이터를 표시할 때 원활하게 작동해야 하지만 첫 번째 방법의 렌더링 시간은 7초라는 끔찍한 시간이 걸렸습니다.
나중에 구현 과정에서 두 가지 주요 성능 문제가 있음을 발견했습니다. 하나는 "ng-repeat" 지시문과 관련이 있고 다른 하나는 필터와 관련이 있습니다.
아래에서는 여러분에게 영감을 주기 위해 다양한 방법을 통해 성능 문제를 해결한 경험을 공유하겠습니다.
1. AngularJS에서 큰 목록을 처리할 때 ng-repeat가 느려지는 이유는 무엇입니까?
AngularJS의 ng-repeat는 2500개가 넘는 양방향 데이터 바인딩을 처리할 때 속도가 느려집니다. 이는 AngularJS가 "더티 검사" 기능을 통해 변경 사항을 감지하기 때문입니다. 각 확인에는 시간이 걸리므로 복잡한 데이터 구조가 포함된 큰 목록으로 인해 애플리케이션 속도가 느려집니다.
2. 성능향상을 위한 전제조건
시간 기록 명령
목록 렌더링에 걸리는 시간을 측정하기 위해 "ng-repeat"의 "$last" 속성을 사용하여 시간을 기록하는 간단한 프로그램을 작성했습니다. 시간은 TimeTracker 서비스에 저장되므로 시간 기록은 서버 측에서 로드되는 데이터와 분리됩니다.
// 렌더링 시간을 기록하기 위한 Post 반복 지시문 angle.module('siApp.services').directive('postRepeatDirective', ['$timeout', '$log', 'TimeTracker', function($timeout, $log, TimeTracker) { return function(scope, element, attrs) { if (scope.$last){ $timeout(function(){ var timeFinishedLoadingList = TimeTracker.reviewListLoaded(); var ref = new Date(timeFinishedLoadingList); var end = new Date(); $log.debug("## DOM 렌더링 목록 사용: " (end - ref) " ms") } } ]); >
Chrome 개발자 도구의 타임라인 속성Chrome 개발자 도구의 타임라인 탭에서는 이벤트, 초당 브라우저 프레임, 메모리 할당을 확인할 수 있습니다. "메모리" 도구는 메모리 누수와 페이지에 필요한 메모리를 감지하는 데 사용됩니다. 페이지 깜박임 문제는 프레임 속도가 초당 30프레임보다 낮을 때 발생합니다. "프레임" 도구는 렌더링 성능을 이해하는 데 도움이 될 수 있으며 JavaScript 작업에 소요된 CPU 시간을 표시할 수도 있습니다.
3. 목록 크기 제한을 통한 기본 튜닝
이 문제를 완화하는 가장 좋은 방법은 표시되는 목록의 크기를 제한하는 것입니다. 이는 페이지 매김과 무한 스크롤 막대 추가를 통해 달성할 수 있습니다.페이지 매김
페이지 매김의 경우 AngularJS의 "limitTo" 필터(AngularJS 버전 1.1.4 이상) 및 "startFrom" 필터를 사용할 수 있습니다. 표시 목록의 크기를 제한하여 렌더링 시간을 줄일 수 있습니다. 이는 렌더링 시간을 줄이는 가장 효율적인 방법입니다.
// 컨트롤러의 페이지 매김 $scope.currentPage = 0; $scope.numberOfPages = function() { return Math.ceil($scope.displayedItemsList.length/ $scope.pageSize) } ; // 필터에서 시작 angle.module('app').filter('startFrom', function() { return function(input, start) { return input.slice(start); }; // HTML에서 사용 // 페이지 매김 버튼{{$index 1}}
페이징을 사용할 수 없거나 사용하고 싶지 않지만 필터링 프로세스가 매우 느린 경우 처음 5개 단계를 확인하고 "ng-show"를 사용하여 중복된 목록 요소를 숨기세요.
무한 스크롤바
이 방법에 대해 더 자세히 알고 싶으시면
http://binarymuse.github.io/ngInfiniteScroll/을 방문하세요.
4. 7가지 튜닝 규칙
1. 데이터 바인딩 없이 목록 렌더링데이터 바인딩이 성능 문제의 원인일 가능성이 가장 높기 때문에 이는 가장 확실한 솔루션입니다. 목록을 한 번만 표시하고 데이터를 업데이트하거나 변경할 필요가 없다면 데이터 바인딩을 포기하는 것이 탁월한 솔루션입니다. 불행하게도 귀하는 귀하의 데이터에 대한 통제권을 상실하지만 우리는 이 법을 사용할 수밖에 없습니다. 자세히 알아보기:
https://github.com/Pasvaz/bindonce.
2. 데이터 계산에 인라인 방식을 사용하지 마세요컨트롤러에서 직접 목록을 필터링하려면 필터 링크를 가져오는 메서드를 사용하지 마세요. "ng-repeat"는 각 [$digest(
http://docs.angularjs.org/api/ng.$rootScope.Scope#$digest)] 표현식을 평가합니다. 우리의 경우 "filteredItems()"는 필터링된 링크를 반환합니다. 평가 프로세스가 느리면 전체 애플리케이션 속도도 빠르게 느려집니다.
//자주 평가해야 하기 때문에 좋은 방법은 아닙니다.
//사용하는 방법입니다
3. 두 개의 목록을 사용합니다(하나는 보기 표시용이고 다른 하나는 데이터 소스로)
전체 데이터 목록에서 표시할 목록을 분리하는 것은 매우 유용한 모델입니다. 일부 필터를 전처리하고 캐시에 저장된 링크를 보기에 적용할 수 있습니다. 다음 사례는 기본적인 구현 과정을 보여줍니다. FilteredLists 변수는 캐시의 링크를 보유하고 applyFilter 메소드는 매핑을 처리합니다.
/* 컨트롤러 */ // 기본 목록 var items = [{name:"John", active:true}, {name:"Adam"}, {name:"Chris"}, {name:"Heather" }]; // 표시 목록 초기화 $scope.displayedItems = items; // 필터 캐시 varfilteredLists['active'] = $filter('filter)(items, {"active" : true}) // 필터 적용 scope.applyFilter = function(type) { if (filteredLists.hasOwnProperty(type){ // 필터가 캐시되었는지 확인 $scope.displayedItems =filteredLists[type]; } else { /* 캐시되지 않은 필터링 */ } } // 재설정 filter $scope.resetFilter = function() { $scope.displayedItems = items } /* 보기 */활성 선택
{{항목.이름}}
4. ng-show 대신 다른 템플릿에서 ng-if 사용
목록 항목의 세부 정보를 표시하기 위해 클릭하는 등 추가 정보를 렌더링하기 위해 지침이나 템플릿을 사용하는 경우 반드시 ng-if(AngularJSv. 1.1.5 이상)를 사용하세요. ng-if는 렌더링을 방지합니다(ng-show와 비교). 따라서 필요에 따라 다른 DOM 및 데이터 바인딩을 평가할 수 있습니다.
위 내용은 AngularJS 성능 튜닝을 위한 7가지 제안에 대한 자세한 설명을 제공합니다.