메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

Dojo TreeGrid의 성능 가속

큰 데이터를 더 빨리 로드

Sheng Hai Xu, Software Engineer, IBM
Photo of Sheng Hai Xu
Sheng Hai Xu is a software engineer with the Globalization Development group at the IBM China Development Lab in Shanghai. He has experience developing web-based tooling with Dojo and Web 2.0 technologies.
Yang Liu, IT 아키텍트, IBM
Li Long Chen은 IBM Managed Business Process Services 솔루션 자산을 위한 IT 아키텍트로 근무하고 있다. 현재는 Self Enablement Portal 프로젝트의 dev/L3 팀장이다. 그는 수 년 동안 대규모 엔터프라이즈 솔루션을 위한 설계 및 개발 업무를 수행했으며 서비스 통합 및 웹 기술 분야에 경험이 있다.
Jie Hu, Staff Software Engineer, IBM  
Photo of Jie Hu
Jie Hu는 IBM China Development Laboratory의 Software Engineer로 5년 간의 J2EE 개발 경력을 보유하고 있다.

요약:  Dojo v1.4 TreeGrid는 웹 페이지에서 계층 구조 데이터를 표시하는 데 유용한 위젯입니다. 하지만, TreeGrid는 큰 데이터 세트에서 작동 시 속도가 극히 느립니다. 본 기사에서는 TreeGridQueryStore를 사용자 정의하여 이 문제를 완화할 수 있는 방법을 배워봅시다.

원문 게재일:  2010 년 12 월 14 일 번역 게재일:  2011 년 4 월 05 일
난이도: 중급 원문:  보기 PDF:  A4 and Letter (511KB | 19 pages)Get Adobe® Reader®
페이지뷰:  1895 회
의견:  


소개

Dojo v1.4 TreeGrid는 웹 페이지에서 계층 구조 데이터를 표시하려 할 때 유용한 위젯이다. 그러나 큰 데이터 세트가 있는 경우 TreeGrid의 성능이 극히 떨어진다. 본 기사에서는 TreeGridQueryStore를 사용자 정의하여 이 문제를 해결할 수 있는 방법을 배워보자. 본 기사에서는 두 개의 위젯을 사용할 때 발생할 수 있는 문제와 오류 발생 이유를 설명한 다음, 솔루션 작성에 도움이 되는 정보를 제공한다. 이 기사에서 사용되는 샘플 코드를 다운로드할 수도 있다.


Dojo 그리드 및 큰 데이터 세트

물론, 그리드를 사용하여 비교적 작은 데이터 세트를 브라우저에서 효과적으로 표시할 수 있다. 이를 통해 정렬, 열 크기 조정 등을 정확하게 수행할 수 있다. 하지만, 특정 시점에서 다룰 수 있는 레코드 수에는 실질적 제한이 있고, 결국 이로 인해 페이지 표시 결과 문제로 이어진다.

이젠, 페이지 표시에 대해서는 잊어도 된다. 이미 해결된 문제이기 때문이다. 그리드가 스크롤할 때 Dojo의 그리드는 느린 DOM(Document Object Model) 렌더링을 사용한다. 수백 개 미만의 레코드를 포함한 비교적 작은 데이터 세트의 경우, 스크롤할 때 느린 DOM 렌더링으로 인해 미리 로드된 데이터 세트를 위한 DOM이 빌드된다. 예를 들어, 100개의 레코드가 있지만 한 번에 20개만 볼 수 있는 경우, 그 특정 섹션으로 스크롤할 때까지 21번째부터 100번째까지의 레코드에 대해서는 노드를 빌드할 필요가 없을 것이다. 열과 관련 태스크를 기준으로 한 정렬은 작은 데이터 세트에 대해 메모리에서 예상대로 작동하고, JavaScript에서 효과적으로 작업을 완료할 수 있다.

매우 큰 데이터 세트의 경우, 열을 기준으로 한 정렬과 같은 태스크를 위해 JavaScript를 사용하는 것은 금방 비현실적으로 되거나, 심지어는 불가능하게 된다. 데이터 세트가 거대한 경우, 모든 데이터를 브라우저로 로드하는 ItemFileReadStore를 이용해 브라우저에서 데이터 세트를 유지보수하려는 것은 현실적이지 못하다.

큰 데이터 세트를 다루기 위한 Dojo의 접근 방법은 간단하고 우수하며, 다음 두 가지로 요약된다.

  • 임의 페이지 크기의 서버에서 데이터를 요청할 수 있는 dojo.data 구현. 이 기사에서는 QueryReadStore를 사용한다.
  • 요청 시 특정 페이지를 요청하고 로드하도록 스크롤할 수 있는 그리드.

본 기사의 나머지 부분에서는 QueryReadStore를 이용해 느리게 로드되는 트리 그리드를 빌드하는 방법을 설명한다.


QueryReadStore, TreeGrid 및 TreeModel

이 섹션에서는 QueryReadStore, TreeGridTreeModel에 대해 매우 기본적인 내용을 소개한다.

QueryReadStore

dojocampus.org 문서(참고자료 참조)에 설명되어 있는 것처럼, QueryReadStoreItemReadStore와 매우 유사하다. 이 두 가지는 모두 JSON을 교환 형식으로 사용한다. 둘 사이에는 데이터 쿼리 방법에 차이가 있다. ItemReadStore는 서버에서 페치 1개를 만들고 클라이언트에서 모든 정렬 및 필터링을 처리한다. 수백 개 정도의 레코드라면 괜찮다. 그러나 수십만 개의 레코드가 있거나 인터넷 연결 속도가 느릴 때는 ItemReadStore가 최적의 방법이 아니다.

QueryReadStore는 각각의 정렬 또는 쿼리를 위해 서버에 대한 요청을 만들므로, dojox.grid.DataGrid에서와 같이 데이터 범위가 작은 큰 데이터 세트에 이상적이다. 목록 1은 QueryReadStore 작성 방법을 나타낸 것이다.


목록 1. QueryReadStore 작성
var url = "./servlet/QueryStoreServlet";
var store = new dojox.data.QueryReadStore({
    url: url,
    requestMethod: "get"
});
            

TreeGrid 및 TreeModel

TreeTreeGrid와 같은 트리 위젯은 계층 구조 데이터 뷰를 표시한다. TreeGrid 위젯 자체는 단지 데이터 뷰일 뿐이다. 진정한 힘은 Tree 위젯이 표시할 실제 계층 구조 데이터를 표시하는 TreeModel에서 나온다.

일반적으로, 데이터는 결국 데이터 저장소에서 오지만, Tree 위젯은 dijit.tree.Model(트리에서 필요로 하는 메소드의 특정 API와 일치하는 오브젝트)과 상호 작용한다. 따라서 Tree 위젯은 항목이 상위 항목을 참조하는 데이터 저장소에서와 같이 다양한 형식의 데이터에 액세스할 수 있다.

TreeModel은 데이터 소스로의 연결, 레이지 로딩 및 Tree 위젯에서 항목과 항목의 계층 구조에 대한 쿼리와 같은 특정 태스크를 담당한다. 예를 들어, 어떤 태스크에서 Tree 위젯에 대한 항목의 하위 항목을 얻을 수도 있다. 또한, TreeModelTree에 데이터 변경 내용을 알리는 역할도 담당한다.

시작하기 위해서는 TreeGrid에 대한 여러 개의 최상위 레벨 항목을 리턴하기 위한 ForestStoreModel(TreeModel의 구현)의 쿼리를 정의할 필요가 있다. 트리가 저장소에 액세스하도록 하기 위한 모델 어댑터도 작성할 것이다. TreeModel을 생성하려면 목록 2의 매개변수가 필요하다.


목록 2. TreeModel을 작성하기 위한 코드
var query = { 
    type: "PARENT" 
}; 

var treeModel = new dijit.tree.ForestStoreModel({ 
    store: store, // the data store that this model connects to 
    query: query, // filter multiple top level items 
    rootId: "$root$", 
    rootLabel: "ROOT", 
    childrenAttrs: ["children"], // children attributes used in data store. 
    /* 
      For efficiency reasons, Tree doesn't want to query for the children 
      of an item until it needs to display them. It doesn't want to query 
      for children just to see if it should draw an expando (+) icon or not. 
      So we set "deferItemLoadingUntilExpand" to true. 
    */ 
    deferItemLoadingUntilExpand: true 
}); 
            

QueryReadStore, TreeGrid 및 TreeModel 사이의 관계

TreeGrid의 사용 방법을 이해하려면 서로 피드하는 다음 트리 컴포넌트를 명심해두자.

  • QueryReadStore는 서버에서 데이터를 페치하는 역할을 담당한다.
  • ForestTreeModelQueryReadStore에서 항목의 계층 구조를 쿼리하여 TreeGrid에 업데이트할 것을 알리는 역할을 담당한다.
  • TreeGrid는 데이터를 표시하고 사용자 이벤트만 처리하는 역할을 담당한다.

그림 1은 이 셋 사이의 관계를 나타낸 것이다. 목록 3은 트리 작성 방법을 나타낸 것이다.


그림 1. QueryReadStore, TreeGrid 및 TreeModel 사이의 관계
queryreadstore, foresttreemodel 및 treegrid를 이용해 서버에서 사용자 이벤트까지의 단계를 보여주는 플로우 차트

목록 3. 트리 작성
// define the column layout for the tree grid. 
var layout = [ 
    { name: "Name", field: "name", width: "20%" }, 
    { name: "Age", field: "age", width: "auto" }, 
    { name: "Position", field: "position", width: "auto" }, 
    { name: "Telephone", field: "telephone", width: "auto" } 
]; 

// tree grid 
var treegrid = new dojox.grid.TreeGrid({ 
    treeModel: treeModel, 
    structure: layout, // define columns layout 
    /* 
      A 0-based index of the cell in which to place the actual expando (+) 
      icon. Here we define the "Name" column as the expando column. 
    */ 
    expandoCell: 0, 
    defaultOpen: false, 
    columnReordering: true, 
    rowsPerPage: 20, 
    sortChildItems: true, 
    canSort: function(sortInfo) { 
        return true; 
    } 
}, "treegrid"); 

treegrid.startup(); 


QueryReadStore가 TreeGrid에서 작동하는 방식

이 섹션에서는 TreeGrid에서 데이터를 렌더링하고, QueryReadStore로 정렬하고, 상위 노드를 확장하는 방법을 설명한다.

렌더링

QueryReadStore는 최상위 레벨 노드를 위해 서버로 요청을 보낸다. 저장소에서 이루어질 서버에 대한 첫 번째 요청은 최상위 레벨 노드(루트의 하위)에 대한 요청이 될 것이다. 이 dojo.data 요청은 특정 JSON 형식을 따른다.

트리 그리드는 모델에 제공되는 쿼리를 사용하여 최초 요청을 수행하고, 저장소에서는 그 요청을 대상과 결합한다. 목록 4는 요청 형식, REST URL 패턴 및 요청에 대한 서버 응답을 나타낸 것이다. 예제에서는 REST 패턴으로 요청이 이루어진다.


목록 4. 쿼리 요청 및 서버 응답
// query 
{ 
  query: {type: "PARENT"}, 
  start: 0, 
  count: 20 //rowsPerPage attribute of the tree grid 
} 

// request sample 
url?type=PARENT&start=0&count=20 

// server response 
{ 
  "identifier": "id", 
  "label": "name", 
  "items": [ 
    { "id": "id_0", 
      "name": "Edith Barney", 
      "age": 39, 
      "position": "Marketing Manager", 
      "telephone": 69000044 
      "children": true, 
      "type": "PARENT" 
    }, 
    { "id": "id_1", 
      "name": "Herbert Jeames", 
      "age": 43, 
      "position": "Brand Executive Manager", 
      "telephone": 69000077, 
      "type": "Child" 
    }, 
    ... 
  ], 
  "numRows": 10000 // total records in the grid 
} 
            

"Edith Barney" 항목은 "PARENT" 유형이고, "Herbert Jeames" 항목 유형은 "Child"이다. 트리 모델에서의 쿼리는 {type: "PARENT"}이므로, 트리 그리드는 처음에는 "Edith Barney" 레코드만 표시한다.

실제로 하위를 포함할 필요는 없고, children 특성이 있다는 것은 노드가 확장 가능하고 확장 아이콘이 포함될 Tree를 가리킨다. "Edith Barney" 항목의 children 속성은 false 값이 아니므로, 트리 모델에서는 그것을 하위를 포함한 노드로 취급한다. 트리 그리드의 Edith Barney 행에 더하기(+) 기호가 있을 것이다. 그림 2는 그 결과를 나타낸 것이다.


그림 2. 작성된 TreeGrid의 렌더링 결과
여러 이름 옆에 + 기호가 있는 이름, 나이, 직함, 직위 및 전화 번호를 표시하는 열

TreeGrid에서 데이터를 렌더링했으므로, 상위 노드 정렬 및 확장과 같은 TreeGrid 기능이 QueryReadStore에서 올바로 작동하는지 확인하고 싶을 것이다.

정렬

정렬 기능을 실행하려면 Name 열의 헤더를 클릭하고 이름을 오름차순으로 정렬한다. 오름차순이나 내림차순으로 다른 열을 정렬하는 경우도 동일하다.


목록 5. 정렬
// the tree model will pass a request to the query store like this: 
{ 
  query: {type: "PARENT"}, 
  start: 0, 
  count: 20, 
  sort: { 
    attribute: "name", 
    descending: false 
  } 
} 

// The query store will request server like this: 
url?type=PARENT&start=0&count=20&sort=name 
            

그림 3은 정렬된 결과를 나타낸 것이다.


그림 3. 정렬된 결과
사전순으로 정렬된 여러 이름 옆에 + 기호가 있는 이름, 나이, 직함, 직위 및 전화 번호를 표시하는 열

상위 노드 확장

큰 트리 데이터 세트의 경우, 아마도 트리 중에서 보이는 노드에 대한 필수 데이터만 로드하고 싶을 것이다. 사용자가 노드를 펼치면 그 노드의 하위 노드가 로드되기 시작한다. 최적의 성능을 위해 확장할 때마다 하나의 HTTP 요청만 하는 것이 이상적이다.

사용자가 예제에 있는 노드 중 하나를 클릭하면 트리에서 저장소에 항목을 로드할 것을 요구하고 저장소에서는 해당 자원을 요청할 것이다. 그러나 더하기 아이콘이 사라지고 하위 행이 표시되지 않는 경우와 같이 이상한 일이 일어날 수도 있다.


그림 4. 확장이 올바로 작동하지 않음
이름, 나이, 직함, 직위 및 전화 번호를 표시하는 열. 한 행에는 + 기호가 없으므로 확장되지 않는다.

그렇다면, 왜 올바로 작동하지 않는 것일까?

목록 6에서 TreeGridTreeModel의 소스 코드를 살펴보고 하위 행 확장이 어떤 식으로 작동하는지 확인해보자.


목록 6. TreeGrid 및 TreeModel이 하위 행을 확장하는 방식
//TreeGrid.setOpen
setOpen: function(open){
    ...

    treeModel.getChildren(itm, function(items){
        d._loadedChildren = true;
        d._setOpen(open);
    });

    ...
} 
//TreeModel.getChilren
getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete,
/*function*/ onError){
    // summary:
    // Calls onComplete() with array of child items of given parent item, all loaded.

    var store = this.store;
    if(!store.isItemLoaded(parentItem)){
    // The parent is not loaded yet, we must be in deferItemLoadingUntilExpand mode,
    // so we will load it and just return the children (without loading each child item) 
        var getChildren = dojo.hitch(this, arguments.callee);
        store.loadItem({
            item: parentItem,
            onItem: function(parentItem){
                getChildren(parentItem, onComplete, onError);
            },
            onError: onError
        });
        return; 
    }
    // get children of specified item
    var childItems = [];
    for(var i=0; i<this.childrenAttrs.length; i++){
        var vals = store.getValues(parentItem, this.childrenAttrs[i]);
        childItems = childItems.concat(vals);
    }
}

트리 모델에서는 우선 저장소에 상위 항목을 로드할 것을 요구한다. 상위 항목은 children 속성이 이 항목의 모든 하위 항목을 나열하는 배열이 아니기 때문에 완전히 로드되지 않는다.

하지만, 아무튼 이 경우는 store.isItemLoaded(parentItem) 검사 논리를 통과하고 childItems=[true]를 가지게 된다. True가 유효한 항목이 아니기 때문에, 트리 그리드는 올바르지 않은 이 하위 항목을 건너뛰어 결국 아무런 일도 일어나지 않는다. 목록 7에서 store.isItemLoaded 메소드에 대한 코드를 검토하여 무슨 일이 일어나고 있는지 살펴보자.


목록 7. store.isItemLoaded
isItemLoaded: function(/* anything */ something){
    // Currently we don't have any state that tells if an item is loaded or not
    // if the item exists it's also loaded.
    // This might change when we start working with refs inside items ...
    return this.isItem(something);
} 
           

이 메소드의 주석에 설명이 나와 있다. QueryReadStore는 현재로서는 부분적으로 항목 로드를 지원하지 않는다.


부분적 로딩을 지원하기 위한 QueryReadStore 사용자 정의

이 섹션에서는 QueryReadStoreTreeGrid를 사용자 정의하여 부분적 로딩을 구현하고 회귀 버그를 수정할 것이다.

사용자 정의된 코드를 전부 다운로드할 수 있다. 이 코드는 Eclipse에서 실행되는 웹 프로젝트로서, 손쉽게 구성된다.

CustomQueryStore 작성

트리 그리드의 확장 함수가 QueryReadStore에서 작동하도록 하려면, 이 함수가 부분적으로 로드된 항목에서 작동하도록 QueryReadStore를 사용자 정의해야 한다. 우선, 클래스를 확장하여 없는 메소드를 추가해야 한다. 목록 8에 표시된 것처럼, 다만 QueryReadStoreCustomQueryStore로 서브클래스화한다.


목록 8. QueryReadStore의 서브클래스화
/* treegrid-demo\WebContent\script\dojo-1.4.3\demo\data\CustomQueryStore.js */ 

dojo.provide("demo.data.CustomQueryStore"); 
dojo.require("dojox.data.QueryReadStore"); 

dojo.declare("demo.data.CustomQueryStore", dojox.data.QueryReadStore, { 
    /* @Override */ 
    isItemLoaded: function(/* anything */ something) { 
        // TODO 
    } 
}); 

목록 9에 표시된 것처럼, 다음 단계는 어떤 항목이 로드되었는지 확인하기 위한 규칙을 변경하는 것이다.


목록 9. isItemLoaded 메소드
/* treegrid-demo\WebContent\script\dojo-1.4.3\demo\grid\CustomTreeGrid.js */ 

/* @Override isItemLoaded method */ 
isItemLoaded: function(/* anything */ something) { 
    // Currently we have item["children"] as a state that tells if an item is 
    // loaded or not. 
    // if item["children"] === true, means the item is not loaded. 
    var isLoaded = false; 

    if (this.isItem(something)) { 
        var children = this.getValue(something, "children"); 
        if (children === true) { 
            // need to lazy loading children 
            isLoaded = false; 
        } else { 
            isLoaded = true; 
        } 
    } 

    return isLoaded; 
} 
            

QueryReadStore에는 loadItem 메소드가 없으므로, 이 메소드를 작성한다. 이 메소드는 해당 항목의 모든 하위 항목을 나열하는 배열을 서버에 요청할 것이다.


목록 10. loadItem, getValues 및 setValues 오버라이드
/* treegrid-demo\WebContent\script\dojo-1.4.3\demo\grid\CustomTreeGrid.js */ 

/* @Override loadItem method */ 
loadItem: function(/* object */ args) { 
    if (this.isItemLoaded(args.item)) { 
        return; 
    } 

    var item = args.item; 
    var scope = args.scope || dojo.global; 
    var sort = args.sort || null; 
    var onItem = args.onItem; 
    var onError = args.onError; 

    if (dojo.isArray(item)) { 
        item = item[0]; 
    } 

    // load children 
    var children = this.getValue(item, "children"); 

    // load children 
    if (children === true) { 
        var serverQuery = {}; 

        // "parent" param 
        var itemId = this.getValue(item, "id"); 
        serverQuery["parent"] = itemId; 

        // "sort" param 
        if (sort) { 
            var attribute = sort.attribute; 
            var descending = sort.descending; 
            serverQuery["sort"] = (descending ? "-" : "") + attribute; 
        } 

        // ajax request 
        var _self = this; 

        var xhrData = { 
            url: this.url, 
            handleAs: "json", 
            content: serverQuery 
        }; 

        var xhrFunc = (this.requestMethod.toLowerCase() === "post") ? 
                       dojo.xhrPost : dojo.xhrGet; 
        var deferred = xhrFunc(xhrData); 

        // onError callback 
             deferred.addErrback(function(error) { 
            if (args.onError) { 
                args.onError.call(scope, error); 
            } 
        }); 

        // onLoad callback 
        deferred.addCallback(function(data) { 
            if (!data) { 
                return; 
            } 

            if (dojo.isArray(data)) { 
                var children = data; 

                var parentItemId = itemId; 
                var childItems = []; 

                dojo.forEach(children, function(childData) { 
                    // build child item 
                    var childItem = {}; 
                    childItem.i = childData; 
                    childItem.r = this; 

                    childItems.push(childItem); 
                }, _self); 

                _self.setValue(item, "children", childItems); 
            } 

            if (args.onItem) { 
                args.onItem.call(scope, item); 
            } 
        }); 
    } 
} 

/* @Override geValues method */ 
getValues: function(item, attribute) { 
    //  summary: 
    //      See dojo.data.api.Read.getValues() 

    this._assertIsItem(item); 
    if (this.hasAttribute(item, attribute)) { 
        return item.i[attribute] || []; 
    } 

    return []; // Array 
} 

/* @Override seValue method */ 
setValue: function(/* item */ item, /* attribute-name-string */ attribute, 
                   /* almost anything */ value) { 
    // summary: See dojo.data.api.Write.set() 

    // Check for valid arguments 
    this._assertIsItem(item); 
    this._assert(dojo.isString(attribute)); 
    this._assert(typeof value !== "undefined"); 

    var success = false; 
    var _item = item.i; 
    _item[attribute] = value; 
    success = true; 

    return success; // boolean 
} 
            

현재 예제에는 새 CustomQueryStore가 있다. 목록 11에 표시된 것처럼, JavaScript에서 QueryReadStore를 바꾼다.


목록 11. CustomQueryStore를 사용하여 요청 보내기
var url = "./servlet/QueryStoreServlet";
var store = new demo.data.CustomReadStore({
    url: url,
    requestMethod: "get"
});
            

이 코드는 그림 5에 표시된 결과를 리턴한다.


그림 5. customQueryStore에 의해 리턴된 결과
관리자 아래의 하위 행에 표시된 직원의 이름, 나이, 직함, 직위 및 전화 번호를 표시하는 열

TreeGrid를 사용자 정의하여 회귀 버그 수정

다른 기능에 대한 검사를 수행하여 CustomQueryStore를 적용한 후 회귀 버그가 없는지 확인할 시점이다.

우선 한 행을 펼친 다음, Name 헤더를 클릭하여 정렬을 수행한다. 그림 6에 표시된 것과 같은 오류가 발생한다.


그림 6. CustomQueryStore를 정렬할 때 오류 발생
첫 번째 행에 'sorry an error occurred'가 표시된 스크린샷

조사를 해보면 트리 그리드가 항상 expando 함수의 상태를 유지한다는 점을 알 수 있다. 정렬 작업 전, 네 번째 행이 펼쳐지고 트리 그리드가 그것을 기억했다. 정렬 작업 후, 항목들이 서로 달랐지만 트리 그리드는 여전히 네 번째 행의 expando 함수를 열려고 할 것이다. 이제 네 번째 행에 대한 항목에 하위 항목이 없기 때문에 오류가 발생했다. 트리 그리드가 정렬 쿼리를 수행할 때 expando 상태를 지울 필요가 있다.

QueryReadStore를 사용자 정의한 것과 같이, TreeGrid를 사용자 정의할 필요가 있다. 그런 다음, CustomTreeGrid를 사용하여 TreeGrid를 바꾸면 정렬 결함이 수정되어야 한다.


목록 12. TreeGrid 사용자 정의
dojo.provide("demo.grid.CustomTreeGrid");
dojo.require("dojox.grid.TreeGrid");
dojo.declare("demo.grid.CustomTreeGrid", dojox.grid.TreeGrid, {
    /* @Override */
    sort: function() {
        this.closeExpando();

        this.inherited(arguments);
    },

    closeExpando: function(identities) {
        if (identities) {
            if (dojo.isArray(identities)) {
                // close multiple expando
                dojo.forEach(identities, function(identity) {
                    this._closeExpando(identity);
                }, this);
            } else {
                // close single expando
                var identity = identities;
                this._closeExpando(identity);
            }
        } else {
            // close all expando
            var expandoCell = this.getCell(this.expandoCell);
            for (var identity in expandoCell.openStates) {
                this._closeExpando(identity);
            }
        }
    },

    _closeExpando: function(identity) {
        var expandoCell = this.getCell(this.expandoCell);

        if (expandoCell.openStates.hasOwnProperty(identity) === true) {
            var open = expandoCell.openStates[identity] || false;
            if (open === true) {
                // clean up expando cache
                this._cleanupExpandoCache(null, identity, null);
            }
        }
    }

});
            

이와 아울러, TreeGridQueryReadStore는 느린 데이터 로드를 해결하기 위한 강력한 조합이다. 미리 대량의 데이터를 전송하지 않고 크고 광범위한 계층 구조 데이터를 표시할 수 있다. QueryReadStore의 부분적 로딩 지원을 활용하여 확장당 단 한 번의 요청으로 레이지 로딩을 수행할 수 있다.


성능 비교

이 기사를 위해, 우리는 ItemFileReadStoreQueryReadStore를 사용하여 TreeGrid 성능을 비교했다. 그림 7과 표 1은 사용자 정의된 QueryStore 및 그리드가 ItemFileReadStore 및 기본 TreeGrid에서 사용하는 시간의 약 1/30만 사용한다는 점을 나타낸다.


그림 7. ItemFileReadStore와 CustomQueryStore 간의 성능 비교
1400으로 판독되는 itemfilereadstore와 100 미만을 표시하는 queryreadstore가 있는 막대 그래프를 보여주는 차트

표 1. 성능 비교
사용되는 데이터 저장소 서버 데이터 로드 시간(s) 그리드 렌더링 시간(s) 총계
ItemFileReadStore 1.45 12.65 14.1
CustomQueryStore 0.14 0.37 0.51

요약

이 기사에서는 Dojo TreeGrid가 큰 데이터를 로드하는 성능을 향상하기 위해 사용자 정의된 솔루션을 작성하는 방법을 배워보았다. QueryReadStore, TreeModelTreeGrid가 함께 작동하여 데이터를 페치하고 렌더링하는 방법을 살펴보았다. QueryStoreTreeGrid를 사용자 정의하면 현재 큰 데이터를 그다지 잘 지원하지 않는 Dojo의 문제점을 해결할 수 있다. 본 기사의 결과에 따르면, 솔루션의 성능은 ItemFileReadStoreTreeGrid가 쓰는 시간의 약 1/30에 불과한 것으로 나타났다.



다운로드 하십시오

설명이름크기다운로드 방식
Sample code for this articletreegrid-demo.zip31KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

토론

필자소개

Photo of Sheng Hai Xu

Sheng Hai Xu is a software engineer with the Globalization Development group at the IBM China Development Lab in Shanghai. He has experience developing web-based tooling with Dojo and Web 2.0 technologies.

Li Long Chen은 IBM Managed Business Process Services 솔루션 자산을 위한 IT 아키텍트로 근무하고 있다. 현재는 Self Enablement Portal 프로젝트의 dev/L3 팀장이다. 그는 수 년 동안 대규모 엔터프라이즈 솔루션을 위한 설계 및 개발 업무를 수행했으며 서비스 통합 및 웹 기술 분야에 경험이 있다.

Photo of Jie Hu

Jie Hu는 IBM China Development Laboratory의 Software Engineer로 5년 간의 J2EE 개발 경력을 보유하고 있다.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=웹 개발
ArticleID=644557
ArticleTitle=Dojo TreeGrid의 성능 가속
publish-date=12142010
author1-email=xshai@cn.ibm.com
author1-email-cc=
author2-email=yangliu@cn.ibm.com
author2-email-cc=
author3-email=hujiesh@cn.ibm.com
author3-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.