자바(JAVA)/JSP 웹 프로그래밍 공부 (성낙현의 JSP 자바 웹 프로그래밍 참고)

JAVA/JSP 29. 회원제 게시판에 페이징 기능 추가2 - 페이징 구현 실습 (JSP)

개발학생 2025. 4. 16. 15:13
반응형

1. DAO 수정

  • 매개변수를 이용해서 페이지별 목록의 범위를 계산했으니, DAO에서 이를 적용한 쿼리문을 실행한 결과를 반환하면 됨
  • BoardDAO 클래스에 게시글 목록을 반환하는 메소드 추가 → selectList() 메소드 아래에 작성
//Java Resources/src/model1/board/BoardDAO.java

... 생략 ...

public class BoardDAO extends JDBConnect {
  ... 생략 ...
  public List<BoardDTO> selectList(Map<String, Object>map) {
    ... 생략 ...
  }

  //검색 조건에 맞는 게시물 목록 반환(페이징 기능 지원)
  public List<BoardDTO> selectListPage(Map<String, Object>map) {
    List<BoardDTO> bbs = new Vector<BoardDTO>();    //결과(게시물 목록)를 담을 변수

    //1.쿼리문 템플릿
    String query = " SELECT * FROM ( "
                 + "  SELECT Tb.*, ROWNUM rNum FROM ( "
                 + "    SELECT * FROM board ";

    //2.검색 조건 추가
    if (map.get("searchWord") != null) {
        query += " WHERE " + map.get("searchField")
              + " LIKE '%" + map.get("searchWord") + "%' ";
    }

    query += "     ORDER BY num DESC "
           + "   ) Tb "
           + " ) "
           + " WHERE rNum BETWEEN ? AND ?";    //3.

    try {
      //4.쿼리문 완성
      psmt = con.prepareStatement(query);
      psmt.setString(1, map.get("start").toString());
      psmt.setString(2, map.get("end").toString());

      //5.쿼리문 실행
      rs = psmt.executeQuery();

      while (rs.next()) {
        //한 행(게시물 하나)의 데이터를 DTO에 저장
        BoardDTO dto = new BoardDTO();
        dto.setNum(rs.getString("num"));
        dto.setTitle(rs.getString("title"));
        dto.setContent(rs.getString("content"));
        dto.setPostdate(rs.getString("postdate"));
        dto.setId(rs.getString("id"));
        dto.setVisitcount(rs.getString("visitcount"));

        //반환할 결과 목록에 게시물 추가
        bbs.add(dto);
      }
    } catch (Exception e) {
      System.out.println("게시물 조회 중 예외 발생");
      e.printStackTrace();
    }

    //목록 반환
    return bbs;
  }

  ... 생략 ...
}
  1. 앞 절에서 설명한 rownum을 이용한 쿼리문 작성(쿼리문 템플릿)
  2. 검색어가 있다면 WHERE절이 추가되도록 if문을 중간에 추가(검색 조건 추가)
  3. 시작 게시물과 끝 게시물을 정하는 BETWEEN 부분을 인파라미터로 설정
  4. 시작과 끝 파라미터를 매개변수로 받은 값으로 채움(=쿼리문 완성)
  5. 쿼리문 실행

2. List.jsp 수정

1) 페이징 설정값 정의: web.xml에 코드 추가

  • 한 페이지에 출력할 게시물의 개수, 한 화면에 출력할 페이지 번호의 개수 설정 → 각각 POSTS_PER_PAGE/PAGES_PER_BLOCK으로, 둘 다 페이지나 페이지 블록을 계산할 때 사용
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi= ... 생략 ...>
  ... 생략 ...

  <context-param>
    <param-name>POSTS_PER_PAGE</param-name>
    <param-value>10</param-value>
  </context-param>
  <context-param>
    <param-name>POSTS_PER_BLOCK</param-name>
    <param-value>5</param-value>
  </context-param>
</web-app>

 

2) 데이터 계산

  • 앞서 작성했던 List.jsp에서, selectCount()와 selectListPage() 메소드 사이에 코드 추가
// WebContent/PagingBoard/List.jsp
<%@ page import="java.util.List"%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Map"%>
<%@ page import="model1.board.BoardDAO"%>
<%@ page import="model1.board.BoardDTO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

... 생략 ...

int totalCount = dao.selectCount(param);    //게시물 수 확인

/***페이지 처리 start***/
//1.전체 페이지 수 계산
int pageSize = Integer.parseInt(application.getInitParameter("POSTS_PER_PAGE"));
int blockPage = Integer.parseInt(application.getInitParameter("POSTS_PER_BLOCK"));
int totalPage = (int)Math.ceil((double)totalCount / pageSize);    //전체 페이지 수

//2.현재 페이지 확인
int pageNum = 1;    //기본값
String pageTemp = request.getParameter("pageNum");
if (pageTemp != null && !pageTemp.equals(""))
   pageNum = Integer.parseInt(pageTemp);    //요청받은 페이지로 수정

//3.목록에 출력할 게시물 범위 계산
int start = (pageNum - 1) * pageSize + 1;    //첫 게시물 번호
int end = pageNum * pageSize;    //마지막 게시물 번호
param.put("start", start);
param.put("end", end);
/***페이지 처리 end***/

List<BoardDTO> boardLists = dao.selectListPage(param);    //4.게시물 목록 받기
dao.close();    //DB 연결 닫기
%>
<!DOCTYPE html>
<html>
<head>
... 생략 ...
  1. 앞에서 상수로 정의한 설정값을 가져와 전체 페이지 수 계산 (계산 결과가 나누어 떨어지지 않으면, 무조건 올림 처리)
  2. 현재 페이지 번호 처리: 처음에는 무조건 1로 설정, 매개변수로 페이지 번호가 넘어오면 그 번호를 사용
  3. 목록에 출력할 게시물의 범위를 계산하여 Map 컬렉션에 저장
  4. DAO에 새로 추가했던 selectListPage() 메소드를 호출하여, 범위에 해당하는 게시물 목록을 가져옴

3) 바로가기 HTML 코드 생성, 화면 출력

  • 목록에 출력할 게시물을 가져왔으니 화면에 출력함

(1) 바로가기 HTML 코드 생성

  • 페이지 바로가기 영역을 HTML 문자열로 출력해주는 메소드 구현 (BoardPage.java 파일에 코드 작성)
// Java Resources/src/utils/BoardPage.java

package utils;

public class BoardPage {
  public static String pagingStr(int totalCount, int pageSize, int blockPage,
      int pageNum, String reqUrl) {
    String pagingStr = "";

    //단계 3: 전체 페이지 수 계산
    int totalPages = (int) (Math.ceil(((double) totalCount / pageSize)));    //1.
		
    //단계 4: '이전 페이지 블록 바로가기' 출력
    int pageTemp = (((pageNum -1) / blockPage) * blockPage) + 1;
    if (pageTemp != 1) {    //2.
      pagingStr += "<a href='" + reqUrl + "?pageNum=1'>[첫 페이지]</a>";    //3.
      pagingStr += "&nbsp;";
      pagingStr += "<a herf='" + reqUrl + "?pageNum=" + (pageTemp -1)
                   +"'>[이전 블록]</a>";    //4.
    }

    //단계 5: 각 페이지 번호 출력
    int blockCount = 1;
    while (blockCount <= blockPage && pageTemp <= totalPages) {
      if (pageTemp == pageNum) {    //5.
        //현재 페이지는 링크를 걸지 않음
        pagingStr += "&nbsp;" + pageTemp + "&nbsp;";
      } else { 
        pagingStr += "&nbsp;<a href='" + reqUrl + "?pageNum=" + pageTemp
                    + "'>" + pageTemp + "</a>&nbsp;";    //6.
      }
      pageTemp++;    //7.
      blockCount++;
    }
		
    //단계 6: '다음 페이지 블록 바로가기' 출력
    if (pageTemp <= totalPages) {    //8.
      pagingStr += "<a href'" + reqUrl + "?pageNum=" + pageTemp
                   + "'>[다음 블록]</a>";    //9.
      pagingStr += "&nbsp;";
      pagingStr += "<a href='" + reqUrl + "?pageNum=" + totalPages
                   + "'>[마지막 페이지]</a>";    //10.
     }

     return pagingStr;
  }
}
  1. 전체 페이지 수 계산
  2. pageTemp가 1이 아닐 때
  3. [첫 페이지] 바로가기 링크 출력 - pageNum=1
  4. [이전 블록] 바로가기 링크 출력 - 현재 6페이지일 경우 pageNum=5
  5. 현재 페이지에서는 링크를 걸지 않기 위해 조건식 사용
  6. 페이지 바로가기
  7. pageTemp를 1씩 증가시키며 6.출력
  8. pageTemp가 전체 페이지 수 이하일 때
  9. [다음 블록] 바로가기 링크 출력
  10. [마지막 페이지] 바로가기 링크 출력 (마지막 페이지가 포함된 블록으로 이동하면 이 영역은 출력되지 않음)
    → pageNum 값으로 전체 페이지 수 사용

(2) 화면 출력

  • List.jsp 파일의 코드 수정
// WebContent/PagingBoard/List.jsp

<%@ page import="java.util.List"%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Map"%>
<%@ page import="model1.board.BoardDAO"%>
<%@ page import="model1.board.BoardDTO"%>
<%@ page import="utils.BoardPage"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
... 생략 ...
<body>
  <!-- 1. -->
  <h2>목록 보기(List) - 현재 페이지: <%= pageNum %> (전체: <%= totalPage %>)</h2>
... 생략 ...
  <!-- 게시물 목록 출력 -->
  <table border="1" width="90%">
    <tr>
      <th width="10%">번호</th>
      <th width="50%">제목</th>
      <th width="15%">작성자</th>
      <th width="10%">조회수</th>
      <th width="15%">작성일</th>
    </tr>

<%
if (boardLists.isEmpty()) {
  // 게시물이 하나도 없을 때
%>
  <tr>
    <td colspan="5" align="center">
      등록된 게시물이 없습니다.
	</td>
  </tr>

<%
} else {
  //게시물이 있을 때
  int virtualNumber = 0;    //화면상에서의 게시물 번호
  int countNum = 0;
  for (BoardDTO dto : boardLists) {
    //virtualNum = totalCount--;    //기존 코드
    irtualNum = totalCount - (((pageNum - 1) * pageSize) + countNum++);    //2.
%>
  <tr align="center">
    <td><%= virtualNum %></td>    <!-- 게시물 번호 -->
    <td align="left">   <!-- 제목(+하이퍼링크) -->
      <a href="View.jsp?num=<%= dto.getNum() %>"><%= dto.getTitle() %></a>
    </td>
    <td align="center"><%= dto.getId() %></td>    <!-- 작성자 아이디 -->
    <td align="center"><%= dto.getVisitcount() %></td>    <!-- 조회수 -->
    <td align="center"><%= dto.getPostdate() %></td>    <!-- 작성일 -->
  </tr>
<%
  }
}
%>
  </table>
  <!-- 목록 하단의 [글쓰기] 버튼 -->
  <table border="1" width="90%">
    <tr align="center">
      <!-- 페이징 처리 -->
      <td>    <!-- 3. -->
        <%= BoardPage.pagingStr(totalCount, pageSize,
	        blockPage, pageNum, request.getRequestURI()) %>
      </td>
      <!-- 글쓰기 버튼 -->
      <td>
        <button type="button" onclick="location.href='Write.jsp';">글쓰기</button>
      </td>
    </tr>
  </table>
</body>
</html>
  1. 제목에 현재 페이지 번호와 총 페이지 수를 출력
  2. 목록 출력 시 사용할 가상 번호 계산
    → 페이지에 따라 출력되는 게시물 범위가 다르므로, 가상 번호에도 페이지 번호가 적용되어 계산되어야 함
    • 전체 게시물 수(totalCount): 106개
    • 페이지 범위(pageSize): 10
    • 1페이지일 때
      • 첫 번째 게시물: 106 - (((1 - 1) * 10) + 0) = 106
      • 두 번째 게시물: 106 - (((1 - 1) * 10) + 1) = 106
    • 2페이지일 때
      • 첫 번째 게시물: 106 - (((2 - 1) * 10) + 0) = 96
      • 두 번째 게시물: 106 - (((2 - 1) * 10) + 1) = 95
  3. 페이지 바로가기 영역 HTML 문자열 출력 메소드 호출
    → 매개변수는 왼쪽부터 ‘전체 게시물 개수’, ‘페이지 범위’, ‘현재 페이지 번호’, ‘실행된 목록 파일명’

3. 동작 확인 

  • 페이지 기능이 추가된 게시판을 실행한 결과 확인

1) [Run As] → [Run On Server]를 클릭하여 List.jsp 파일 실행

  • 첫 실행 시 pageNum 매개변수가 전달되지 않으니 1페이지로 인식함
    → 이전 블록도 없기 때문에, 아무것도 출력되지 않음

 

2) [다음 블록] 바로가기 링크 클릭

  • 현재 페이지 블록의 크기를 5로 설정하였으므로, 다음 블록은 6
  • 매개변수로 pageNum=6이 전달되는 것을 볼 수 있고, 게시물도 55번(105 - 50)이 첫 번째로 출력됨
  • 첫 페이지가 아니므로 [이전 블록] 바로가기 링크도 출력됨

반응형