클라이언트 처리의 한계와 OData 서버사이드의 필요성
대용량 데이터를 FlexGrid에 바인딩하면 브라우저에서 필터·정렬·페이징 성능이 급격히 떨어집니다. 특히 수만 건 이상에서는 스크롤 지연과 메모리 부담이 눈에 띄게 커집니다. 이때 서버가 정렬·필터·페이징을 수행하고 클라이언트는 필요한 페이지만 받아오는 구조가 현실적인 해법입니다. 네트워크 트래픽과 렌더링 비용을 동시에 줄일 수 있습니다.
ODataCollectionView는 OData 표준 쿼리(예: $filter, $orderby, $top, $skip)를 자동으로 구성해 서버 요청을 만들어 줍니다. 별도의 커스텀 API 없이도 FlexGrid와 자연스럽게 연동됩니다. 이 글은 처음 적용하는 분도 따라 할 수 있도록, ODataCollectionView로 서버사이드 필터·정렬·페이징을 단계별로 구현하는 방법과 주의점을 실무 관점에서 정리합니다.
OData 쿼리와 ODataCollectionView가 맞물리는 방식
대부분의 업무 화면은 “주문일이 최근 30일, 금액 내림차순, 50건씩 보기” 같은 요구를 가집니다. OData는 이를 $filter, $orderby, $top, $skip 파라미터로 표준화해 URL만으로 표현하고, 서버는 해당 조건의 데이터 조각만 반환합니다.
ODataCollectionView는 이 표준 쿼리를 대신 조립해 줍니다. 사용자가 그리드에서 정렬 헤더를 클릭하거나 필터를 바꾸면, 뷰가 자동으로 $orderby나 $filter를 포함한 요청을 만들고 새 페이지를 로드합니다.
실무 흐름은 단순합니다.
- 데이터 원본: OData 엔드포인트(예: /Orders)
- 조건 입력: 그리드 정렬/필터/페이지 변경
- 결과 수신: 서버가 조건에 맞는 레코드와 총 개수를 돌려줌
아래 예시는 구조를 보여주기 위한 형태입니다.
요지는 “그리드 동작 → ODataCollectionView가 쿼리 생성 → 서버가 필요한 페이지만 응답”의 루프가 자연스럽게 이어진다는 점입니다.
OData 그리드 서버 처리: 최소 설정 가이드
서버사이드 정렬·필터·페이징은 다음 순서로 간단히 구성합니다.
- OData 엔드포인트 확인: $filter, $orderby, $top, $skip, $count
- ODataCollectionView 생성: 서비스 URL, 엔드포인트, 키 필드
- FlexGrid 바인딩: 페이징 UI와 정렬·필터 트리거 연결
- 총 개수·페이지 처리: count 허용, pageSize 지정
그리드 조건 변경 시 URL 쿼리를 자동 생성하려면 데이터 소스로 ODataCollectionView를 쓰고 pageSize·count를 명시하세요. 핵심은 뷰가 서버 파라미터를 대신 구성하도록 환경을 맞추는 것입니다.
아래 예시는 필터·정렬·페이징을 서버에서 처리하는 기본 구조입니다.
<div id="grid"></div>
<div>
<button id="prev">이전</button>
<span id="info"></span>
<button id="next">다음</button>
</div>
<script type="module">
import * as wjOData from '@grapecity/wijmo.odata';
import * as wjGrid from '@grapecity/wijmo.grid';
const cv = new wjOData.ODataCollectionView(
'https://services.odata.org/V4/Northwind/Northwind.svc', 'Orders', {
keys: ['OrderID'], pageSize: 50,
sortOnServer: true, filterOnServer: true, pageOnServer: true,
inferDataTypes: true, requestHeaders: { Accept: 'application/json' }
});
const grid = new wjGrid.FlexGrid('#grid', {
itemsSource: cv, allowSorting: true, selectionMode: 'Row', isReadOnly: true
});
prev.onclick = () => { if (cv.pageIndex > 0) cv.moveToPage(cv.pageIndex - 1); };
next.onclick = () => { if (cv.pageIndex < cv.pageCount - 1) cv.moveToPage(cv.pageIndex + 1); };
cv.collectionChanged.addHandler(() => {
info.textContent = `${cv.pageIndex + 1} / ${cv.pageCount}`;
});
const since = new Date(Date.now() - 30*24*60*60*1000).toISOString();
cv.filterDefinition = `OrderDate ge ${since}`;
</script>
동작 매핑: 클릭 정렬→$orderby, 페이지 이동→$skip/$top, 필터 변경→$filter. 체크포인트:
- 날짜·문자열은 OData 규격(UTC, 따옴표) 준수
- 대역폭 제한 시 $select로 필요한 열만 요청
- 지연·오류 대비: 로딩 표시, cv.error 핸들러 추가
흔한 함정과 선택 기준: 카운트, 필터 구문, 페이지 상태
서버가 $count를 지원하지 않으면 총 레코드 수가 0으로 들어와 페이지 계산이 틀어집니다. count 결과를 확인하고 없으면 별도 엔드포인트나 추정 로직을 고려하세요.문자열 비슷함 검색을 OData의 contains로 바꾸지 않으면 서버가 전체 스캔을 유발할 수 있습니다. 필드 타입에 맞는 연산자(contains, startswith, ge/le, eq)를 명확히 매핑하세요.
정렬 키가 인덱스 없는 컬럼이면 요청마다 지연이 커집니다. 자주 정렬·필터하는 컬럼에 인덱스를 두고, 서버 응답에 정렬 안정성(secondary key)도 함께 고려하세요.페이지 이동 중 사용자 입력이 겹치면 이전 응답이 뒤늦게 도착해 화면이 뒤바뀌는 경우가 있습니다. 요청 취소(AbortController)나 타이핑 지연 처리(debounce 200~300ms)로 경쟁 상태를 완화하시기 바랍니다.
선택 기준은 다음이 실용적입니다.
- 필터가 단순·규모가 작다: 클라이언트 처리
- 다중 조건·대량 데이터·보안 필터 필요: OData 서버사이드
- 비정형 검색(전문 검색, 점수 랭킹): 별도 검색 API + 최소 필드만 OData로 병행
필드명 매핑이 바뀔 수 있는 백엔드라면, 클라이언트에서 컬럼-서버필드 딕셔너리를 두고 한 곳에서 관리하시면 됩니다. 쿼리 실패 시 사용자에게 조건을 유지한 채 재시도 버튼을 제공하면 이탈을 줄일 수 있습니다.
지금 적용할 체크리스트와 다음 단계
이번 글의 핵심은 FlexGrid에 ODataCollectionView를 연결해 정렬·필터·페이징을 서버로 넘기고, 클라이언트는 필요한 페이지만 그리는 구조입니다. 첫 목표는 페이지 크기와 카운트 지원을 명확히 하고, 필터·정렬 구문을 OData 표준에 맞추는 것입니다.
바로 실행할 순서는 다음과 같습니다.
- OData 엔드포인트에서 $filter/$orderby/$top/$skip/$count 동작 확인
- ODataCollectionView 생성 시 serviceUrl, entity, key, pageSize, requestHeaders 점검
- FlexGrid에 바인딩하고 Sort/Filter UI 활성화, 페이지 네비게이션 연결
- AbortController로 이전 요청 취소, 텍스트 필터에는 debounce 적용
- 자주 거르는 컬럼에 인덱스 추가, 문자열 검색은 contains/startswith로 통일
필요하다면 간단한 헬퍼로 요청 경쟁을 막을 수 있습니다. 아래는 페이지 전환 시 이전 요청을 취소하는 예시입니다.
let ac;
function loadPage(view, pageIndex) {
if (ac) ac.abort();
ac = new AbortController();
view.pageIndex = pageIndex;
view.requestOptions = { signal: ac.signal };
}
포인트는 새 페이지를 지정할 때 기존 네트워크를 끊어 화면 뒤집힘을 방지하는 것입니다. 이 흐름만 잡으면 대용량 목록도 안정적으로 구동됩니다.
네트워크 쿼리로 이벤트-요청 상관관계 점검
서버 사이드 흐름은 개발자도구에서 요청 URL·쿼리를 직접 확인하는 것이 가장 빠릅니다. 그리드 동작이 OData 파라미터($filter, $orderby, $top, $skip)로 정확히 매핑되는지 보세요.
정렬 클릭, 필터 입력, 페이지 이동을 최소 예시로 재현하고, 이벤트와 전송된 URL을 함께 기록합니다. 아래 코드는 구조를 보여주는 형태입니다.
const view = new wijmo.odata.ODataCollectionView({
serviceUrl: '/odata',
entity: 'Orders',
keys: ['OrderID'],
pageSize: 50,
requestHeaders: { Prefer: 'odata.maxpagesize=50' }
});
const grid = new wijmo.grid.FlexGrid('#grid', { itemsSource: view });
view.loading.addHandler(() => console.log('로딩 시작'));
view.loaded.addHandler((s) => console.log('완료:', s['_getRequestUrl']?.() || '(URL 확인 필요)'));
grid.sortedColumn.addHandler(() => console.log('정렬 변경'));
grid.collectionView.collectionChanged.addHandler((s, e) => {
if (e.action === wijmo.collections.NotifyCollectionChangedAction.Reset) console.log('페이지/필터 갱신');
});
이렇게 제스처→서버 파라미터 흐름이 드러나면 필터 구문 오류, 중복 요청, 과도한 페이지 재로딩 같은 병목을 빠르게 식별할 수 있습니다.
'프로그래밍 > wijmo' 카테고리의 다른 글
| Wijmo MultiRow 그리드로 폼형 레이아웃 구성: 초보자용 작성 가이드 (0) | 2026.06.02 |
|---|---|
| Wijmo FlexGrid 정렬(Sorting) 기능 정리 (0) | 2026.02.19 |
| Wijmo 데이터 그리드 셀 병합(Merging) 기능 (0) | 2026.02.10 |
| 자바스크립트 OLAP 내보내기 - Wijmo (0) | 2025.09.30 |
| OLAP 슬라이서 기능 - Wijmo (0) | 2025.09.24 |