GridView의 senseReader 속성 사용 시 유의 사항

성능 비교 (예시)

GridView와 바인딩 된 데이터가 1,000건이고 visibleRowNum="all" 설정을 적용한 경우에 대한 예시입니다. visibleRowNum="all" 설정을 적용했기 때문에 1,000건의 데이터가 한번에 표시됩니다.

senseReader="false" visibleRowNum="all"

위의의 결과는 겉으로만 보기에는 senseReader="true"인 경우와 senseReader="false"인 경우에는 다른 차이가 없습니다. 성능 비교를 위해 메모리 사용량과 DOM 개체 수를 확인해 보겠습니다.

Heap 메모리

브라우저의 개발 도구에서 Memory 탭을 선택한 후 Containment를 엽니다. "mf_"로 시작하는 GridView의 개체 노드를 확인할 수 있습니다.

개발자 도구 (Memory – Containment)

Heap 스냅 샷으로 GridView의 메모 사용량을 확인할 수 있습니다.

senseReader="false"

GridView (id="mf_wdc_main_subWindow2_wframe_grd_basic" ) 개체가 사용하는 Retained Size의 값이 약 234kb임을 알 수 있습니다. Retained Size는 가비지 컬렉션이 해당 개체를 제거할 때 반환될 수 있는 Heap 메모리의 크기입니다.

Heap 스냅샷 (senseReader="false")

senseReader="true"

senseReader="true"인 경우에는 동일한 GridView 컴포넌트 개체가 사용하는 Retained Size의 값이 약 334kb임을 알 수 있습니다. 즉, senseReader="false"인 경우와 비교할 때, Heap 메모리를 42% 정도 더 사용합니다.

Heap 스냅샷 (senseReader="true")

DOM 개체 수

전역 변수로 생성된 GridView 컴포넌트와 관련된 DOM 개체 수를 확인해 보겠습니다. 개발자 도구의 Console 탭에서 아래의 스크립트를 사용하십시오 .

$r_title(개발자 도구 –  Console 탭)
Object.keys(window)
  .filter(x => x.startsWith("mf_wdc_main_subWindow2_wframe_grd_basic"))
  .length;

senseReader="false"

senseReader="false"인 경우에는 단 1개의 개체만 생성됩니다.

senseReader="true"

senseReader="true"인 경우에는, 5,002개의 GridView 컴포넌트와 관련된 WebSquare 컴포넌트 개체가 생성됩니다. senseReader="false"인 경우에는 1개가 생성되는 것과 비교하면 5,001개의 차이가 있습니다. 이 차이는 "행의 수(1,000) X 각 컬럼의 Input 컴포넌트 수 (5) + fakeInput(1) = 5001"로 계산할 수 있습니다.

senseReader 메모리 사용량

브라우저의 작업 관리자에서 메모리 사용량을 확인할 수 있습니다.

메모리

네이티브 메모리의 사용량을 보여주며 DOM 개체는 이 네이티브 메모리에 저장됩니다.

JavaScript 메모리

JavaScript Heap 메모리의 사용량을 보여줍니다. 괄호 안에 표시된 값은 페이지에서 도달 가능한 활성 개체의 메모리 사용량을 보여줍니다.

senseReader="false"

브라우저 작업 관리자

senseReader="true"

브라우저 작업 관리자

결론

다음은 위의 예제를 비교한 표입니다. senseReader="true"인 경우, senseReader="false"와 비교하여 더 많은 리소스를 사용한다는 점을 알 수 있습니다.

성능 비교

항목

senseReader="false"

senseReader="true"

Heap 메모리 (Retained Size)

234kb

334kb (약 1.5배 높음.)

DOM 개수

1

5,002

(네이티브) 메모리

311,908kb

479,960kb (약 1.5배 높음.)

JavaScript 메모리

13,630kb

62,431kb (약 4.5배 높음.)

위의 비교는 단순한 기본 예제를 테스트한 것으로 실제 프로젝트에서는 senseReader="true" 설정이 초래하는 영향도가 훨씬 클 수 있습니다. 수천 건 이상의 데이터가 GridView와 바인딩되거나 , 수십 개의 컬럼이 존재하거나, TabControl의 여러 탭에 GridView들이 존재할 수도 있습니다.

기술적인 측면에서 senseReader="true" 설정으로 인한 변화를 이해하고 다른 속성들과의 상호 작용을 확인한 후 senseReader 속성을 사용할 것을 권장합니다.

렌더링 방식 (drawType)

virtual 렌더링 (drawType="virtual")

다음은 컬럼 5개와 행 100개로 구성된 GridView를 화면에 표시한 예시입니다. 현재 5개의 행이 브라우저에 출력되어 있습니다.

GridView (컬럼 5개 X 행 100개)

브라우저의 개발자 도구를 사용하여 렌더링 결과를 확인하면 <tbody> 태그 하위에는 현재 화면에 출력된 5개의 행수와 동일하게 <tr> 태그는 5개만 존재합니다. 스크롤 아래로 이동해도 <tr> 태그 개수는 5개로 유지됩니다. 각 <tr> 태그의 rowindex는 변경되지만 전체 <tr> 태그 개수는 5개로 유지됩니다. 이와 같은 렌더링 방식을 drawType="virtual" 설정을 통한 virtual 방식이라고 합니다.

GridView 렌더링 결과

각 셀의 값은 <input> 태그가 아닌 <span> 태그 내에 존재합니다. gridView.columninputType에 따라 화면 렌더링에 적합한 DOM 개체들이 사용됩니다. 참고로 아래 예제에서 gridView.columninputType"text"입니다.

<tr> 노드 확장

해당 셀 데이터를 편집하는 동안에 렌더링 상태는 변경되지 않습니다. 이는 셀 편집 시 해당 셀의 DOM 구성 자체가 변경되는 것이 아니라, 편집을 위한 <input> 태그 등 별도의 DOM 개체가 개발자가 지정한 컬럼 설정에 따라 해당 위치의 Z축 위로 적절히 이동하여 나타나는 것이기 때문입니다. F12 개발자 도구를 이용해서 이를 쉽게 확인해 볼 수 있습니다. 다음은 Z축 위치를 덮고 있는 <input> 태그의 좌표를 살짝 변경하여 우하단으로 약간 이동시킨 모습입니다.

<input> 태그 좌표 이동 후

GridView의 이 같은 virtual 방식의 렌더링은 상대적으로 많은 대량의 데이터를 용이하게 관리할 수 있는 이점을 제공합니다. 불필요한 대량의 DOM 개체들을 생성하지 않기 때문에 페이징 기법을 사용하지 않고서도 웹 브라우저의 부하 없이 대량의 데이터를 다룰 수 있습니다. 보통 컬럼의 수가 많고 복잡한 편집 컴포넌트를 사용할 수록 DOM 개체에 의한 부하가 심해지지만, virtual 방식으로 렌더링할 경우 부하가 늘어는 것을 방지할 수 있습니다.

하지만 virtual 렌더링 방식의 단점도 있습니다. 웹 접근성 지원을 위한 스크린 리더 기능의 경우 시각 장애인에게 읽어줘야 할 대상이 왜곡될 가능성이 매우 높습니다. 일례로 <input> 태그로 인식되어야 할 셀이 <span> 태그로 인식될 수 있습니다.

native 렌더링 (drawType="native")

drawType="native" 설정을 사용하면 바인딩 된 데이터의 건수와 동일한 건수의 <tr> 태그를 생성합니다. 아래 그림을 보면 GridView아 바인딩된 전체 데이터 건수와 1:1로 대응하여 <tr> 태그가 생성된 것을 확인할 수 있습니다.

drawType="native"

native 렌더링 방식은 virtual 렌더링 방식에 비해 브라우저에 가해지는 부하가 크고 무겁습니다. senseReader="true" 설정까지 적용하면 visibleRowNum="all" 설정을 적용한 것과 거의 동일한 수준의 영향을 줍니다. native 렌더링과 virtual 렌더링 방식의 차이는 virtual 렌더링 방식에서는 GridView의 높이가 자동으로 변경된다는 것입니다.

native 렌더링 방식 사용 시 고려할 점

바인딩 된 데이터 건수가 많거나 senseReader="true" 설정이 적용된 경우 높은 부하를 감당해야 함

데이터를 편집하지 않는 읽기 전용 GridView 컴포넌트인 경우 권장

데이터를 편집해야 하는 GridView 컴포넌트인 경우, 바인딩 되는 데이터 건수를 가급적 적게 유지할 것을 권장

GridView 대신 Generator 사용을 검토

native 렌더링 방식으로 해결할 수 있는 대표적은 상황은 아래와 같습니다.

(1) UI적인 측면의 불만을 해소해야 할 때

아래의 예시에서 보듯이 drawType="virtual" 설정을 적용할 경우 GridView 행 일부가 가려지는 경우가 발생합니다. 이 경우 native 렌더링 방식을 활용하는 것이 한 가지 해법이 될 수 있습니다.

drawType="virtual"

(2) 비-웹스퀘어적인 방법을 통한 GridView의 변경 사항을 유지

웹스퀘어 API가 아닌 (비-웹스퀘어적인) 방법을 통해 GridView를 변경하고, 이 변경 사항을 스크롤바 이동에 상관 없이 유지해야 할 경우 drawType="native" 설정을 사용하여 해결할 수 있습니다.

다음은 Vanilla JS 코드를 실행하여 특정 셀의 색상을 변경한 경우입니다.

$r_title(Vanilla JS 코드)
document.querySelector("#mf_wdc_main_subWindow2_wframe_grd_basic_cell_1_1")
    .style
    .setProperty("color", "red");

위와 같이 특정 셀의 색상을 변경한 후, 스크롤바를 내리고 다시 올리면 셀의 변경한 셀의 색상이 유지되지 않고 원래 색상으로 돌아오는 것을 볼 수 있습니다.

변경된 셀 색상을 유지하려면 GridView의 setCellColor() 함수를 사용하여 셀 색상을 변경해야 합니다.

$r_title(setCellColor() 사용 예)
gridView1.setCellColor(1, 1, "red");

그러나 WebSquare에서 필요한 API를 지원하지 않거나, jQuery 또는 Vanilla JS 등을 직접 사용할 수밖에 없는 (특정 조건에서 새로운 DOM 구조를 직접 생성하여 삽입해야 하는 등의) 경우에는, drawType="native" 렌더링 방식을 사용하여 스크롤바 이동에 상관없이 GridView의 변경 사항을 유지할 수 있습니다.