[Nexacro N] Grid Paging — 페이징 처리

Nexacro N Grid의 pageRowCount와 currentPage로 클라이언트 페이징을 구현하는 방법, 서버사이드 페이징 패턴, 페이지 이동 UI 구현을 설명합니다.

· 6 min read · PALDYN Team

지난 글에서 정렬과 필터 처리 방법을 살펴봤습니다. 이번에는 대량 데이터를 다룰 때 필수적인 페이징(Paging) 처리를 다룹니다. Nexacro N은 클라이언트 페이징과 서버사이드 페이징 두 가지 방식을 지원합니다.

페이징의 두 가지 방식

방식원리적합한 데이터 규모
클라이언트 페이징전체 데이터를 한 번에 로드 후 페이지 분할중용량 (수백수천 건)
서버사이드 페이징페이지 요청마다 서버에서 해당 페이지 데이터만 수신대용량 (수만 건 이상)

Grid 페이징 처리 구조

클라이언트 페이징 — pageRowCount

Grid의 pagerowcount 속성에 페이지당 표시할 행 수를 지정하면 클라이언트 페이징이 활성화됩니다.

<Grid id="grd_emp"
  pagerowcount="20"
  bindDataset="ds_emp">
</Grid>

pagerowcount="20"을 설정하면 Dataset의 전체 행 중 현재 페이지에 해당하는 20개 행만 Grid에 표시됩니다.

관련 속성

속성설명
pagerowcount페이지당 표시 행 수
currentpage현재 페이지 인덱스 (0-based)
pagecount전체 페이지 수 (read-only)
function fn_initPaging() {
  // Grid의 총 페이지 수 확인
  var totalPage = this.grd_emp.pagecount;
  // 현재 페이지 확인
  var curPage = this.grd_emp.currentpage;
  trace("현재: " + (curPage + 1) + "페이지 / 전체: " + totalPage + "페이지");
}

페이지 이동 함수

클라이언트 페이징 구현 코드

페이지 이동은 grd.currentpage 값을 변경하는 방식으로 구현합니다.

function fn_movePage(pageIdx) {
  var totalPage = this.grd_emp.pagecount;
  if (pageIdx < 0 || pageIdx >= totalPage) return;

  // Grid 페이지 변경
  this.grd_emp.currentpage = pageIdx;
  // Dataset 현재 행을 해당 페이지 첫 번째 행으로 이동
  this.ds_emp.rowposition =
    pageIdx * this.grd_emp.pagerowcount;

  // 페이지 표시 레이블 갱신
  this.lbl_page.set_text(
    (pageIdx + 1) + " / " + totalPage
  );
}

function btn_prev_onclick(obj, e) {
  this.fn_movePage(this.grd_emp.currentpage - 1);
}

function btn_next_onclick(obj, e) {
  this.fn_movePage(this.grd_emp.currentpage + 1);
}

function btn_first_onclick(obj, e) {
  this.fn_movePage(0);
}

function btn_last_onclick(obj, e) {
  this.fn_movePage(this.grd_emp.pagecount - 1);
}

페이지 번호 버튼 동적 생성

페이지 번호 버튼 목록을 동적으로 생성하려면 페이지 수에 따라 버튼을 추가/제거하는 방식을 사용합니다.

function fn_buildPageButtons() {
  var totalPage = this.grd_emp.pagecount;
  var curPage = this.grd_emp.currentpage;

  // 최대 5개 버튼 표시 (앞뒤 2페이지)
  var startPage = Math.max(0, curPage - 2);
  var endPage = Math.min(totalPage - 1, startPage + 4);

  // 기존 버튼 초기화 후 재생성 로직
  // (실제 구현은 Dynamic 컴포넌트 활용)
  for (var i = startPage; i <= endPage; i++) {
    var isActive = (i == curPage);
    // 버튼 텍스트: i + 1, 현재 페이지 강조
    trace("페이지 버튼: " + (i + 1) +
      (isActive ? " [현재]" : ""));
  }
}

서버사이드 페이징

대용량 데이터에서는 서버에 현재 페이지 번호와 페이지 크기를 전달해 해당 페이지 데이터만 받아오는 방식이 필요합니다.

var g_currentPage = 1;
var g_pageSize = 20;
var g_totalCount = 0;

function fn_search(pageNo) {
  g_currentPage = pageNo;

  this.ds_search.setColumn(0, "page_no", pageNo);
  this.ds_search.setColumn(0, "page_size", g_pageSize);

  this.transaction(
    "getEmpPage",
    this.getSvcUrl("getEmpPage"),
    "ds_search=ds_search",
    "ds_emp=ds_emp ds_meta=ds_meta",
    "",
    "fn_searchCallback"
  );
}

function fn_searchCallback(svc, errCode, errMsg) {
  if (errCode != 0) return;

  // 서버에서 전체 건수 수신 (ds_meta에 저장)
  g_totalCount = this.ds_meta.getColumn(0, "total_count");

  // 전체 페이지 수 계산
  var totalPage = Math.ceil(g_totalCount / g_pageSize);

  // 페이지 UI 갱신
  this.lbl_page.set_text(
    g_currentPage + " / " + totalPage
  );
}

서버사이드 페이징에서는 pagerowcount를 사용하지 않습니다. 트랜잭션으로 받은 데이터가 이미 한 페이지 분량이므로 Dataset 전체를 표시합니다.

무한 스크롤 (Infinite Scroll)

페이지 버튼 대신 스크롤 끝에 도달할 때 다음 페이지를 자동 로드하는 무한 스크롤 패턴도 구현할 수 있습니다.

function grd_emp_onvscrollchanged(obj, e) {
  var maxScrollPos = obj.vscrollmax;
  var curScrollPos = obj.vscrollpos;

  // 스크롤이 끝에서 10% 이내에 도달하면 추가 로드
  if (curScrollPos >= maxScrollPos * 0.9) {
    if (!g_loading) {
      g_loading = true;
      this.fn_search(g_currentPage + 1, true); // append=true
    }
  }
}

onvscrollchanged 이벤트에서 스크롤 위치를 감지해 추가 데이터를 요청합니다.

페이징과 필터/정렬 조합

클라이언트 페이징 상태에서 filter()를 적용하면 필터된 행 기준으로 페이지 수가 재계산됩니다.

function fn_filterAndPage(dept) {
  this.ds_emp.filter("dept_cd == '" + dept + "'");
  // 필터 후 첫 페이지로 이동
  this.fn_movePage(0);
}

필터 적용 직후에는 반드시 첫 페이지로 이동해야 합니다. 필터로 행 수가 줄어 현재 페이지가 범위를 벗어날 수 있습니다.

정리

pagerowcount로 클라이언트 페이징을 활성화하고, currentpage를 변경해 페이지를 이동합니다. 대용량 데이터는 서버사이드 페이징으로 페이지 번호를 서버에 전달해 해당 페이지 데이터만 수신합니다. 필터/정렬과 페이징은 독립적으로 동작하므로 조합 시 현재 페이지를 초기화해야 합니다.


지난 글: Nexacro N Grid Sort & Filter — 정렬과 필터

다음 글: Nexacro N Grid Row Actions — 행 단위 액션


읽어주셔서 감사합니다. 😊