프로그래밍 일기/Java & Spring

JAVA 페이징 처리 및 알고리즘

MakeMe 2022. 7. 6. 22:51
반응형

DB에서 필요 데이터 가져오기

String SQL = "select * from (select rownum rnum, board.* from\r\n" + 
             "(select * from board order by NUM desc) board)\r\n" + 
             "where rnum >= ? and rnum <=?";

ROWNUM을 사용하면 가상의 번호를 불러올 수 있습니다.

하지만 ROWNUM은 가상의 번호이기 때문에 만약 ROWNUM 2~10처럼 시작이 1이 아닌 2가 나온다면 에러가 납니다. 그렇기에 가상의 숫자(RNUM)을 하나 더 만들어서 DB에서 값을 가져와야 합니다.

ROWNUM에 관한 주의사항과 여러 내용이 들어있는 블로그를 소개합니다.

https://rios.tistory.com/entry/Oracle-ROWNUM-%EC%A3%BC%EC%9D%98-%EC%82%AC%ED%95%AD%ED%8E%98%EC%9D%B4%EC%A7%95-or-%EC%A0%95%EB%A6%AC%EC%8B%9C

 

[Oracle] ROWNUM 주의 사항(페이징 or 정리시)

[Oracle] ROWNUM 주의 사항(페이징 or 정리시) ▼ WHERE or ORDER BY 절 이없을때 1. 주로 착각 하고 잘못 사용 경우 1 2 3      SELECT ROWNUM, COL1, COL2  FROM TABLE_NAME ORDER BY COL1 ASC;..

rios.tistory.com

 

페이징 알고리즘

페이징 알고리즘에서 가장 중요한 것은 블록과 현재 페이지 값입니다.

한 블럭에 몇 개의 게시물이 들어갈지 생각한 후 그 게시물에 맞게 총 몇 페이지 까지 글이 나와야 하는지가 블록입니다. 만약 101개의 글이 있고, 한개의 페이지에 10개의 게시물이 보인다면 101/10 = 10, 10개의 블록하고 1개의 게시물이 더 있으니 11번 째 블록도 만들어 져야 합니다. 이 개념을 알고 코드를 보면 좀 더 쉽게 이해할 수 있을겁니다.

package action;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import board.BoardDAO;
import board.BoardDTO;

public class ListAction extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		List<BoardDTO> list = null;
		BoardDAO dao = new BoardDAO();
		int articleCount = dao.articleCount(); // 총 글 갯수
		
		int pageN; // 현재 페이지 넘버
		int countList = 5; // 한 페이지에 보여줄 글 갯수
		int countPage = 3; // 페이지 갯수 ex ) [1] [2] [3] 다음
		int block = articleCount / countList ;
		if(articleCount % countList != 0){
			block++;
		}
		String pageNum = req.getParameter("pageNum");
		if (pageNum == null) {
			pageN = 1;
		}else {
			pageN = Integer.parseInt(pageNum);
			if(pageN <= 0 ) {
				pageN = 1;
			}
			if(pageN > block) {
				pageN -= 3;
			}
		}
		
		int startPage = (pageN-1) / countPage * countPage + 1; // 시작 페이지
		int endPage = startPage + countPage - 1; // 끝 페이지
		if (endPage > block) {
			endPage = block;
		}
		int start = pageN*5 - 4;
		int end = pageN*5;
		list = dao.getList(start, end); // 해당 페이지에 맞는 게시물 불러오는 메서드
		
		req.setAttribute("startPage", startPage);
		req.setAttribute("endPage", endPage);
		req.setAttribute("list", list);
		req.setAttribute("articleCount", articleCount);
		req.setAttribute("currentPage", pageN);
		req.setAttribute("countPage", countPage);
		req.getRequestDispatcher("/board/list.jsp").forward(req, resp);
	}
}

 

위 코드는 게시판을 불러올 때 서블릿을 통해 실행되는 코드입니다. 위 코드를 토대로 아래 list.jsp에 보내준 정보가 어떻게 사용되는지 보여드리겠습니다.

<nav>
  <ul class="pagination" style="text-align:center;">
    <li class="page-item">
        <a class="page-link" href="${pageContext.request.contextPath}/list?pageNum=${(endPage - 3)}" aria-label="Previous">
            <span aria-hidden="true">&laquo;</span>
        </a>
    </li>

    <c:forEach var="i" begin="${startPage }" end="${endPage }">
        <li class="page-item"><a class="page-link" href="${pageContext.request.contextPath}/list?pageNum=${i}">${i}</a></li>
    </c:forEach>

    <li class="page-item">
        <a class="page-link" href="${pageContext.request.contextPath}/list?pageNum=${startPage + 3}" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
        </a>
    </li>
  </ul>
</nav>

 

맨 위 <li> 가 이전페이지로 넘어가는 것이고 가운데 [1][2][3] 부분이 페이지 넘버 가장 하단에 있는 부분이 다음페이지 입니다.

살펴볼 부분은 가운데 있는 c:forEach 부분입니다. jstl을 아직 모른다면 이해하기 힘들 수 있습니다. jstl 알고 있다는 가정하에 처음 자바 코드에서 만든 startPage와 endPage만으로 페이징 처리가 가능하게 됩니다. 그리고 이전 버튼은 마지막 페이지 - countPage 다음 버튼은 첫 페이지 + countPage로 pageNum을 변화시켜 주었습니다.

더 궁금하신 점이 있다면 댓글 남겨주십시오.

 

반응형