eGovFrame

전자정부 프레임워크에서 페이징 처리하기

jki09871 2025. 2. 5. 21:34
전자정부 프레임워크(이하 eGovFramework)는 국내 공공기관과 정부 프로젝트에서 자주 사용되는 프레임워크입니다. 이 글에서는 전자정부 페이징(PaginationInfo)을 활용하여 페이징 기능을 구현하는 방법을 다룹니다.

📌 1. 전자정부 프레임워크의 페이징 개요

전자정부 프레임워크는 PaginationInfo 클래스를 제공하여 간단한 설정만으로 페이징 기능을 구현할 수 있습니다.

페이징은 일반적으로 다음과 같은 과정을 거칩니다:

  1. 사용자의 요청(현재 페이지 정보)을 컨트롤러에서 받음
  2. PaginationInfo 객체를 생성하고 페이징 관련 값을 설정
  3. MyBatis 또는 SQL에서 데이터 조회를 위한 시작 인덱스(firstRecordIndex)와 페이지당 데이터 개수(recordCountPerPage)를 서비스 계층으로 전달
  4. 서비스 계층에서 DB에서 데이터를 조회
  5. 뷰에서 PaginationInfo를 활용하여 페이징 UI 렌더링

📌 2. 페이징을 위한 DTO 생성

페이징 처리를 위한 DTO는 firstRecordIndex와 recordCountPerPage 값을 포함해야 합니다.

package com.carwash.dto;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class PagingDTO {
    private int firstRecordIndex; // LIMIT 시작 위치
    private int recordCountPerPage; // 한 페이지당 데이터 개수
}

✔️ firstRecordIndex는 SQL의 OFFSET 역할을 하며, recordCountPerPage는 LIMIT 값으로 사용됩니다.


📌 3. 컨트롤러에서 페이징 처리

컨트롤러는 사용자의 요청에서 pageNo(현재 페이지)를 받고, PaginationInfo 객체를 통해 페이징 정보를 설정합니다.

@Controller
@RequestMapping("/api/v1/notifications")
public class NotificationController {

    @Autowired
    private NotificationService notificationService;

    @GetMapping("/list.do")
    public String notificationList(
            @RequestParam(value = "pageNo", required = false, defaultValue = "1") int pageNo,
            Model model) {

        // 1️⃣ PaginationInfo 객체 생성
        PaginationInfo paginationInfo = new PaginationInfo();
        paginationInfo.setCurrentPageNo(pageNo); // 현재 페이지 번호
        paginationInfo.setRecordCountPerPage(10); // 한 페이지에 표시할 데이터 개수
        paginationInfo.setPageSize(10); // 화면에 표시할 페이지 개수 (1~10, 11~20)

        // 2️⃣ firstRecordIndex와 recordCountPerPage 설정
        int firstRecordIndex = paginationInfo.getFirstRecordIndex();
        int recordCountPerPage = paginationInfo.getRecordCountPerPage();

        // 3️⃣ DTO에 페이징 정보 저장
        PagingDTO pagingDTO = new PagingDTO();
        pagingDTO.setFirstRecordIndex(firstRecordIndex);
        pagingDTO.setRecordCountPerPage(recordCountPerPage);

        // 4️⃣ 총 게시물 개수 조회
        int totalRecords = notificationService.notificationTotalCount();
        paginationInfo.setTotalRecordCount(totalRecords); // 전체 게시물 수 설정

        // 5️⃣ 페이징을 적용한 리스트 조회
        List<NotificationVO> notifications = notificationService.notificationListPaging(pagingDTO);

        // 6️⃣ 모델에 데이터 추가하여 뷰로 전달
        model.addAttribute("notificationVO", notifications);
        model.addAttribute("paginationInfo", paginationInfo);

        return "/notification/list"; // JSP 또는 타임리프 뷰
    }
}

✔️ PaginationInfo는 페이지의 시작 인덱스를 자동으로 계산해주므로, 이를 PagingDTO에 담아 DB 조회에 사용합니다.
✔️ notificationTotalCount()를 호출해 전체 게시물 개수를 조회하고, 이를 PaginationInfo에 설정하여 총 페이지 수를 계산할 수 있도록 합니다.


📌 4. 서비스 계층에서 페이징 적용한 데이터 조회

서비스 계층에서는 PagingDTO를 사용하여 페이징 정보를 기반으로 데이터를 가져옵니다.

@Service
public class NotificationService {

    @Autowired
    private NotificationMapper notificationMapper;

    public int notificationTotalCount() {
        return notificationMapper.selectTotalNotificationCount();
    }

    public List<NotificationVO> notificationListPaging(PagingDTO pagingDTO) {
        return notificationMapper.selectNotificationList(pagingDTO);
    }
}

✔️ notificationTotalCount()는 전체 게시물 개수를 조회하는 SQL을 실행합니다.
✔️ notificationListPaging(PagingDTO pagingDTO)는 LIMIT과 OFFSET을 적용하여 해당 페이지의 데이터만 가져옵니다.


📌 5. MyBatis Mapper 설정

MyBatis의 Mapper.xml에서 페이징을 위한 SQL을 작성합니다.

    <select id="notificationList" parameterType="pagingDTO" resultMap="notificationVOMap">
        SELECT
              ID
            , TITLE
            , CONTENT
            , CREATED_AT
            , UPDATED_AT
            , DELETED_AT
            , IS_DELETED
            , HITS
        FROM
            NOTIFICATION
        ORDER BY
            ID DESC
        LIMIT
            #{firstRecordIndex}, #{recordCountPerPage}
    </select>

    <select id="notificationTotalCount"  resultType="int">
        SELECT
            COUNT(*)
        FROM
            NOTIFICATION
    </select>

✔️ COUNT(*)를 사용하여 전체 데이터 개수를 조회합니다.
✔️ LIMIT #{recordCountPerPage} OFFSET #{firstRecordIndex}를 적용하여 현재 페이지에 해당하는 데이터만 조회합니다.


📌 6. JSP에서 페이징 UI 출력

전자정부 페이징 기능을 활용하여 UI에 페이징 버튼을 추가합니다.

<%@ taglib uri="http://egovframework.gov/egovTag" prefix="ui" %>

<div style="text-align: center">
    <ui:pagination paginationInfo="${paginationInfo}" type="text" jsFunction="linkPage"/>
</div>

<script>
function linkPage(pageNo) {
    location.href = "/api/v1/notifications/list.do?pageNo=" + pageNo;
}
</script>

✔️ ui:pagination 태그를 사용하면 자동으로 [처음] [이전] 1 2 3 4 5 [다음] [마지막] 버튼이 생성됩니다.
✔️ jsFunction="linkPage"를 설정하면 페이지 버튼 클릭 시 linkPage(pageNo) 함수가 실행되며, 해당 페이지로 이동합니다.


📌 7. 커스텀 페이징 렌더러

전자정부 페이징 UI를 커스터마이징하려면 DefaultPaginationRenderer 클래스를 수정할 수 있습니다.

package com.util;

import egovframework.rte.ptl.mvc.tags.ui.pagination.AbstractPaginationRenderer;

public class DefaultPaginationRenderer extends AbstractPaginationRenderer {
    public DefaultPaginationRenderer() {
        firstPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return false;\">[처음]</a>&#160;";
        previousPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return false;\">[이전]</a>&#160;";
        currentPageLabel = "<strong>{0}</strong>&#160;";
        otherPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return false;\">{2}</a>&#160;";
        nextPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return false;\">[다음]</a>&#160;";
        lastPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return false;\">[마지막]</a>&#160;";
    }
}

✔️ <a> 태그 안의 {0}({1})는 jsFunction="linkPage"에서 전달된 함수명과 페이지 번호로 치환됩니다.


📌 결론

  1. PaginationInfo를 활용하면 쉽고 강력한 페이징을 구현 가능
  2. 컨트롤러에서 PaginationInfo를 설정하고, 서비스는 데이터 조회만 담당
  3. MyBatis에서 LIMIT과 OFFSET을 사용하여 페이징된 데이터 조회
  4. 전자정부 태그(ui:pagination)를 사용하면 자동으로 UI 생성
  5. 필요하면 DefaultPaginationRenderer를 수정하여 UI를 커스터마이징 가능

 

참고 자료 : https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:rte:ptl:view:paginationtag

 

egovframework:rte:ptl:view:paginationtag [eGovFrame]

전자정부프레임워크에서는 페이징 처리의 편의를 위해 <ui:pagination/> 태그를 제공한다. 페이징 기능을 사용할때 기능은 유사하지만 이미지나 라벨등의 포맷만 다양하게 사용하게 되는 경우가 있

www.egovframe.go.kr

 

 참고 영상(완벽한 해설) :  https://www.youtube.com/watch?v=XLfbdEF0Gfs