JAVA 페이징 처리 및 알고리즘
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에 관한 주의사항과 여러 내용이 들어있는 블로그를 소개합니다.
[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">«</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">»</span>
</a>
</li>
</ul>
</nav>
맨 위 <li> 가 이전페이지로 넘어가는 것이고 가운데 [1][2][3] 부분이 페이지 넘버 가장 하단에 있는 부분이 다음페이지 입니다.
살펴볼 부분은 가운데 있는 c:forEach 부분입니다. jstl을 아직 모른다면 이해하기 힘들 수 있습니다. jstl 알고 있다는 가정하에 처음 자바 코드에서 만든 startPage와 endPage만으로 페이징 처리가 가능하게 됩니다. 그리고 이전 버튼은 마지막 페이지 - countPage 다음 버튼은 첫 페이지 + countPage로 pageNum을 변화시켜 주었습니다.
더 궁금하신 점이 있다면 댓글 남겨주십시오.