2014년 11월 27일

JSP 페이징 처리 구현 하기


출처 : http://dualist.tistory.com/147

매번 페이징을 구현할 때마다, 한 두시간 씩 끙끙대는 것 같다.
생각을 의사코드로 적은 후에 그걸 코드화 하는 습관을 들여야하는데,
성질이 급해서 일단 생각을 코드화 해서 버그를 잡은 다음에.. 그제서야 의사코드로 적고 있다.
다음은 생각의 흐름를 정리해본 것이다.
************************************************************************************************

 총 데이터 수가 37개인 데이터를 페이징 처리 해보자.
 데이터는 DB에서 가져오거나 xml파일을 읽어올 것이다.
  페이지를 3 페이지씩 보여줄 수도 있고 [1] [2] [3] [다음]
 혹은 10페이지씩 보여줄 수도 있다. [1] [2] [3] [4] [5] ...[10] [다음]
 값 셋팅에 따라 달라질 수 있도록 페이지그룹 사이즈(pageGroupSize) 변수를 사용하겠다.
 셋팅할 수 있는 값이 페이지그룹 사이즈 말고 또 무엇이 있을까?
  한 페이지 당 보여주는 리스트 갯수도 변할 가능성이 많다.
 이것은 페이지 사이즈(pageSize) 변수로 놓자.
 그러면, 페이징 로직의 결과를 예측하기 위해서 이 두개의 변수에 값을 넣어보자.

 총 데이터 갯수 (count): 37

 페이지그룹 사이즈 (페이지그룹을 몇개씩 묶을 것인가) : 3
 페이지 사이즈 (한 페이지 당 리스트 갯수): 4
 이렇게 셋팅을 할 경우, 나오는 결과는?
 총 페이지 수(pageCount)는 37 / 4 = 9.25 니까 10 페이지 되겠다.
  pageCount = (count / pageSize ) + ( count % pageSize == 0 ? 0 : 1);
  => count % pageSize == 0 ? 0 : 1 이 수식을 풀어서 쓰면
            if(count % pageSize == 0)
                return 0;
            else
                return 1;
    이렇게 표현된다.
 =============================================================================
                                     
          [1][2][3]   [4][5][6]   [7][8][9]   [10]
 페이지그룹넘버(numPageGroup) :   - 1 -           - 2 -           - 3 -      - 4 -
 =============================================================================

 페이지 그룹은 위와같이 총 4개로 나올 것이다. (pageGroupCount : 4)
 이 페이지 그룹을 본 후, 현재페이지가 호출될 경우를 생각해보면
 5페이지가 호출된다면 numPageGroup이 2인 상태로 페이지바가 보여질 것이다.
 그렇다면, 호출된 현재페이지를 가지고 페이지그룹넘버를 구하고,
 페이지그룹넘버값으로 페이지바의 첫번째 페이지를 계산해보자.

 numPageGroup = 올림(currentPage/pageGroupSize)
  => int numPageGroup = (int) Meth.ceil ((double)currentPage/pageGroupSize)                  
 => numPageGroup : 올림(5/3) = 2
 startPage = (numPageGroup - 1)*pageGroupSize + 1;
 => stratPage : (2-1)*3+1 = 4
 이제 시작페이지를 가지고 마지막 페이지도 구해보자
 endPage = startPage + pageGroupSize -1 => 4+3-1 = 6
 이런식으로 시작페이지와 마지막페이지를 구했다면, for문을 돌려서 페이지바를 출력할 수 있을 것이다.
 그런데, 마지막 페이지그룹을 위 공식대로 계산하면 endPage가 12페이지가 나온다.
  총 페이지수가 10개인데 12페이지까지 출력되면 안 될것이다.
 따라서, if문 처리를 추가해주자.
 if( 마지막페이지 > 총페이지 )
  마지막페이지 = 총 페이지    => endPage = 10
************************************************************************************************
로직은 자바 클래스로, 출력부분은 JSTL 코드로 작성했는데.. 페이징 부분 코드는 다음과 같다.

[ 자바 클래스 ]
          //한 페이지 당 보여줄 글 갯수 
17:         private final static int pageSize = 4;
18:         //페이지그룹안의 페이지 갯수 ex) [이전] 1 2 3 4 5 [다음] 일 경우 페이지 갯수는 5
19:         private final static int pageGroupSize = 3;
             String pageNum = request.getParameter("pageNum");//페이지 번호
25:
26:         if (pageNum == null) {
27:             pageNum = "1";
28:         }
29:        
30:         int currentPage = Integer.parseInt(pageNum);
31:         int startRow = (currentPage - 1) * pageSize + 1;//한 페이지의 시작글 번호
32:         int endRow = currentPage * pageSize;//한 페이지의 마지막 글번호
33:         int count = 0;
34:         int number=0;

35:         ArrayList articleList = new ArrayList();
36:         BoardDAO dbPro = BoardDAO.getInstance();//DB연동
37:         count = dbPro.getTotalCnt();//전체 글의 수
38:        
39:         if (count > 0) {       
40:                 if(endRow>count)
41:                         endRow = count;
42:             articleList = dbPro.select(startRow,endRow);//현재 페이지에 해당하는 글 목록
43:            
44:         } else {
45:             articleList = null;
46:         }
47:                
48:                 number=count-(currentPage-1)*pageSize;//글목록에 표시할 글번호
49:                
50:                 //페이지그룹의 갯수 
51:                 //ex) pageGroupSize가 3일 경우 '[1][2][3]'가 pageGroupCount 개 만큼 있다.  
52:                 int pageGroupCount = count/(pageSize*pageGroupSize)+( count % (pageSize*pageGroupSize)== 0 ? 0 : 1);
53:                 //페이지 그룹 번호 
54:                 //ex) pageGroupSize가 3일 경우  '[1][2][3]'의 페이지그룹번호는 1 이고  '[2][3][4]'의 페이지그룹번호는 2 이다.
55:                 int numPageGroup = (int) Math.ceil((double)currentPage/pageGroupSize);
          //해당 뷰에서 사용할 속성
57:         request.setAttribute("currentPage", new Integer(currentPage));
58:         request.setAttribute("startRow", new Integer(startRow));
59:         request.setAttribute("endRow", new Integer(endRow));
60:         request.setAttribute("count", new Integer(count));
61:         request.setAttribute("pageSize", new Integer(pageSize));
             request.setAttribute("number", new Integer(number));
63:         request.setAttribute("pageGroupSize", new Integer(pageGroupSize));
64:         request.setAttribute("numPageGroup", new Integer(numPageGroup));
65:         request.setAttribute("pageGroupCount", new Integer(pageGroupCount));
66:         request.setAttribute("articleList", articleList);
67:       
68:         return "./list.jsp";//해당 뷰


[ JSP 부분 ]
<c:if test="${count > 0}">
   <c:set var="pageCount" value="${count / pageSize + ( count % pageSize == 0 ? 0 : 1)}"/>
   <c:set var="startPage" value="${pageGroupSize*(numPageGroup-1)+1}"/>
   <c:set var="endPage" value="${startPage + pageGroupSize-1}"/>
  
   <c:if test="${endPage > pageCount}" >
     <c:set var="endPage" value="${pageCount}" />
   </c:if>
         
   <c:if test="${numPageGroup > 1}">
        <a href="./list.do?pageNum=${(numPageGroup-2)*pageGroupSize+1 }">[이전]</a>
   </c:if>

   <c:forEach var="i" begin="${startPage}" end="${endPage}">
       <a href="list.do?pageNum=${i}">[
        <font color="#000000" />
          <c:if test="${currentPage == i}">
          <font color="#bbbbbb" />
        </c:if>
        ${i}
       </font>]
       </a>
   </c:forEach>

   <c:if test="${numPageGroup < pageGroupCount}">
        <a href="./list.do?pageNum=${numPageGroup*pageGroupSize+1}">[다음]</a>
   </c:if>
</c:if>