이번 포스팅에서는 내가 학원에서 JSP를 활용하여 간단한 게시판 페이징을 구현하는 방법을 배워 온것을 까먹지 않게 기록해둠의 목적과 이 알고리즘에 대해 공유하고자 적어보려한다.
Paging Algorithm이란 사용자가 요청한 페이지에 해당하는 게시글을 데이터베이스에서 가져와서 보여주는 기능이다. 이를 위해서는 다양한 클래스와 메서드를 사용하며, 각각의 역할과 동작 원리를 자세하게 파헤쳐 보자!
1. 페이징 알고리즘 이해하기
우선, 페이징 알고리즘을 이해해야 한다. 사용자가 요청한 페이지 번호와 전체 게시글 수를 기반으로 필요한 정보를 계산한다.
이 때 필요한 항목은 다음과 같다.
- reqPage: 사용자가 요청한 페이지 번호
- totalBoard: 총 게시글 수
- boardCount: 한 페이지에 출력할 게시글 수
- totalPage: 총 페이지 수
- offset: SQL에서 데이터를 가져올 시작점
- pageCount: 한 페이지에 출력할 페이지 번호 수
- section: 페이지 숫자를 구분하는 인덱스 역할
- begin, end: 각 섹션에서의 시작 페이지와 끝 페이지 번호
- prev, next: 이전/다음 섹션 존재 여부
2. 페이징 알고리즘 코드 작성하기
위에서 설명한 페이징 알고리즘을 바탕으로 Java 코드를 작성하여 페이징을 구현한다.
Paging 클래스를 사용하여 필요한 정보를 계산하고, DAO는 데이터베이스로부터 데이터를 가져오는 역할을 한다.
package service;
public class Paging {
private int reqPage; // 사용자가 요청한 페이지
private int totalBoard; // 총 게시글 수
private int boardCount = 10; // 한 페이지에 출력할 게시글 수
private int totalPage; // 전체 페이지 수
private int offset; // SQL에서 게시글을 가져올 시작점
private int pageCount = 10; // 한 페이지에 출력할 페이지 번호 수
private int section; // 페이지 번호 범위를 구분할 index 역할
private int begin; // 해당 section에서 첫 페이지 번호
private int end; // 해당 section에서 끝 페이지 번호
private boolean prev, next; // 이전/다음 section 존재 여부
public Paging(int reqPage, int totalBoard) {
// 1. 외부로 부터 전달 받아야 하는 데이터(요청 페이지, 전체 글 수)
this.reqPage = reqPage;
this.totalBoard = totalBoard;
// 2. 전체 페이지 수를 구한다
totalPage = totalBoard / boardCount;
totalPage += (totalBoard % boardCount == 0) ? 0 : 1;
// 3. 게시글을 분할에 필요한 offset을 구한다
offset = (reqPage - 1) * boardCount;
// 4. 페이지 숫자 범위 나누기
section = (reqPage - 1) / pageCount;
begin = section * pageCount + 1;
end = (section + 1) * pageCount;
end = (end < totalPage) ? end : totalPage;
// 5. 이전/다음 section이 있는지 판별
prev = section != 0;
next = totalPage != end;
}
// 이하 Getter/Setter 메서들은 생략한다.
}
public int totalBoard() {
String sql = "select count(*) as count from board";
try {
stmt = getStatement();
rs = stmt.executeQuery(sql);
rs.next();
return rs.getInt("count");
} catch (SQLException e) {
System.out.println("totalBoard 예외 : " + e.getMessage());
} finally {
close();
}
return 0;
}
public <T> Map<String, Object> query(String sql, int reqPage, Mapper<T> mp) {
Map<String, Object> map = new HashMap<>();
Paging pg = new Paging(reqPage, totalBoard());
try {
pstmt = getPrepared(sql);
pstmt.setInt(1, pg.getOffset());
pstmt.setInt(2, pg.getBoardCount());
rs = pstmt.executeQuery();
List<T> list = new ArrayList<T>();
while (rs.next()) {
list.add(mp.mapping(rs));
}
map.put("list", list);
map.put("pg", pg);
return map;
} catch (SQLException e) {
System.out.println("query 예외 : " + e.getMessage());
} finally {
close();
}
return null;
}
3. Controller와 JSP에서 페이징 구현하기
마지막으로, Controller와 JSP 파일에서 페이징을 구현한다.
Controller에서는 요청을 받아 DAO를 통해 데이터를 가져오고, JSP에서는 해당 데이터를 화면에 출력한다.
package controller;
import java.io.IOException;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import model.DAO;
import model.Mapper;
import model.vo.BoardVO;
@WebServlet("/home")
public class HomeController extends HttpServlet {
private static final long serialVersionUID = -8753957661320028246L;
private Mapper<BoardVO> mp = (ResultSet rs) -> {
BoardVO row = new BoardVO();
row.setContents(rs.getString("contents"));
row.setIdx(rs.getInt("idx"));
row.setNick(rs.getString("nick"));
row.setTitle(rs.getString("title"));
row.setV_count(rs.getInt("v_count"));
row.setW_date(rs.getDate("w_date"));
return row;
};
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String pageParam = req.getParameter("page");
int reqPage = pageParam != null ? Integer.parseInt(pageParam) : 1;
DAO dao = new DAO();
String sql = "select * from board_view " +
"order by idx desc " +
"offset ? rows " +
"fetch first ? rows only";
Map<String, Object> map = new HashMap<>();
map = dao.query(sql,reqPage, mp);
req.setAttribute("map", map);
RequestDispatcher rd;
rd = req.getRequestDispatcher("/WEB-INF/home.jsp");
rd.forward(req, resp);
}
}
<!-- JSTL태그를 이용하여 map으로 받아온 게시글 리스트와 페이지를 각각 변수로 저장 -->
<c:set var="list" value="${map['list'] }"/>
<c:set var="pg" value="${map['pg'] }"/>
<!-- 대충 게시글 출력하는 구간 ㅇㅅㅇ -->
<ul class="page">
<!-- 이전 페이지 링크 -->
<c:if test="${pg.prev }">
<li><a href="${cpath }/home?page=${pg.begin - 1 }">
이전
</a></li>
</c:if>
<!-- 페이지 번호 링크 -->
<c:forEach var="i" begin="${pg.begin }" end="${pg.end }">
<li><a href="${cpath }/home?page=${i }">
${i }
</a></li>
</c:forEach>
<!-- 다음 페이지 링크 -->
<c:if test="${pg.next }">
<li><a href="${cpath }/home?page=${pg.end + 1 }">
다음
</a></li>
</c:if>
</ul>
이렇게 구현된 코드는 사용자가 요청한 페이지에 해당하는 게시글을 화면에 표시해준다.
페이징 기능을 이용하면 데이터를 효율적으로 관리하고 사용자 경험을 향상시킬 수 있다. (사실상 페이징 안되어있는 사이트는 없음..)
이상으로, JSP를 활용하여 간단한 게시판 페이징을 구현하는 방법에 대해 알아보았습니다!!
각 코드와 동작 원리를 자세히 설명하여 이해를 돕기 위해 노력했습니다만 이해하기 쉬웠는지는 모르겠네요...
저도 다음에 써먹을 때 기억이 잘안나면 다시 제가 쓴글을 되돌아보며 코드작성 해보도록 하지요..