전자정부 프레임워크 공부

게시판 페이지네이션 기능 구현 [전자정부 프레임워크 공부]

그랜파 개발자 2025. 5. 18. 14:12

게시판 페이지네이션 기능 만들어 줘

ChatGPT의 말:

 

Eclipse Dynamic Web Project + MySQL 게시판에 페이지네이션 기능을 추가하는 간단한 예제를 보여드릴게요.

서블릿과 JSP 양쪽에서 10개씩 페이지 그룹을 나누는 페이지네이션 으로 구현합니다.


게시판 페이징 기본 개념

  • 한 페이지에 보여줄 게시글 수를 정합니다. 예: 10개
  • 현재 페이지 번호를 받아서, SQL에서 LIMIT와 OFFSET을 사용해 해당 페이지에 맞는 글을 불러옵니다.
  • 전체 게시글 수를 구해서 총 페이지 수를 계산합니다.
  • JSP에서 페이지 번호 링크를 출력해 페이지 이동 가능하게 만듭니다.

게시판에서 페이지네이션을 할 때, 총 페이지 개수를 10개씩 묶어서 페이지 네비게이션(페이지 그룹) 으로 보여주려면?

예를 들어, 총 페이지가 35면:

  • 1 ~ 10 페이지 그룹
  • 11 ~ 20 페이지 그룹
  • 21 ~ 30 페이지 그룹
  • 31 ~ 35 페이지 그룹 이런 식으로 나누는 거예요.

 

  • pageSize = 10 (한 페이지에 보여줄 게시글 수)
  • pageGroupSize = 10 (한번에 보여줄 페이지 링크 개수)
  • currentPage = 현재 사용자가 보고 있는 페이지 번호
  • totalPages = 전체 페이지 수

1. MySQL 게시글 불러오기 쿼리 수정하기

SELECT * FROM posts ORDER BY created_at DESC LIMIT ? OFFSET ?;
  • LIMIT : 한 페이지에 보여줄 글 개수 (예: 10)
  • OFFSET : 건너뛸 글 개수 ((page - 1) * limit)

2. 게시글 상세보기

postView

postView는 게시글 상세보기 페이지로, 특정 게시글 ID를 받아서 DB에서 해당 글을 조회해 보여주는 기능입니다.


1. PostViewServlet.java (서블릿)

package controller;

import java.io.IOException;
import java.sql.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

import dao.BoardDAO;
import model.Post;

@WebServlet("/postView")
public class PostViewServlet extends HttpServlet {

    private BoardDAO dao = new BoardDAO();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String idStr = request.getParameter("id");
        if (idStr == null || idStr.isEmpty()) {
            response.sendRedirect("posts");  // id가 없으면 목록으로 리다이렉트
            return;
        }

        int id = 0;
        try {
            id = Integer.parseInt(idStr);
        } catch (NumberFormatException e) {
            response.sendRedirect("posts");
            return;
        }

        try  {
            Post post = dao.getPostById(id);

            if (post == null) {
                response.sendRedirect("posts");  // 게시글 없으면 목록으로
                return;
            }

            String pageParam = request.getParameter("page");
            int currentPage = 1;
            if (pageParam != null) {
                try {
                    currentPage = Integer.parseInt(pageParam);
                } catch (NumberFormatException e) {
                    currentPage = 1;
                }
            }

            request.setAttribute("currentPage", currentPage);

            request.setAttribute("post", post);
            request.getRequestDispatcher("/postView.jsp").forward(request, response);

        } catch (SQLException e) {
            throw new ServletException(e);
        }
    }
}

2. BoardDAO.java에 상세보기 메서드 추가

public Post getPostById(int id) throws SQLException {
    String sql = "SELECT * FROM posts WHERE id = ?";
    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setInt(1, id);
        ResultSet rs = pstmt.executeQuery();

        if (rs.next()) {
            Post post = new Post();
            post.setId(rs.getInt("id"));
            post.setTitle(rs.getString("title"));
            post.setContent(rs.getString("content"));
            post.setCreatedAt(rs.getTimestamp("created_at"));
            return post;
        }
        return null;
    }
}

3. postView.jsp (게시글 상세보기 JSP)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="model.Post" %>

<%
    Post post = (Post) request.getAttribute("post");
    if (post == null) {
%>
    <p>게시글을 찾을 수 없습니다.</p>
<%
    } else {
%>
<html>
<head>
    <title><%= post.getTitle() %> - 게시글 상세</title>
</head>
<body>
    <h2><%= post.getTitle() %></h2>
    <p><em>작성일: <%= post.getCreatedAt() %></em></p>
    <hr>
    <div><pre><%= post.getContent() %></pre></div>

    <%
        int currentPage = 1;
        if (request.getAttribute("currentPage") != null) {
            currentPage = (Integer) request.getAttribute("currentPage");
        }
    %>

    <hr>
    <!-- 목록으로 가기 버튼 -->
    <a href="board?page=<%= currentPage %>">목록으로</a>

</body>
</html>
<%
    }
%>

정리

  • postView 서블릿에서 id 파라미터 받아서 게시글 조회
  • DAO에 getPostById 메서드 추가
  • 조회된 게시글을 JSP로 넘겨 상세보기 출력

2. DAO 수정하기

package dao;

import model.Post;
import java.sql.*;
import java.util.*;

public class BoardDAO {
    private static final String URL = "jdbc:mysql://localhost:3306/boarddb?useSSL=false&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true";
    private static final String USER = "root";        // 본인 DB 계정
    private static final String PASSWORD = "qwerty!";

    private Connection getConn() throws SQLException {
        //return DriverManager.getConnection(URL, USER, PASSWORD)  
        try {
            // Load the MySQL JDBC driver
            Class.forName("com.mysql.cj.jdbc.Driver"); // Use the appropriate driver class name
            return DriverManager.getConnection(URL, USER, PASSWORD);
        } catch (Exception e) {
            e.printStackTrace(); // Handle any exceptions
        }
        return null;
    }

    // 게시글 전체 개수 가져오기
    public int getTotalPosts() throws SQLException {
        String sql = "SELECT COUNT(*) FROM posts";
        try (Connection conn = getConn();
                PreparedStatement pstmt = conn.prepareStatement(sql);
                ResultSet rs = pstmt.executeQuery())
        {
            if (rs.next()) {
                return rs.getInt(1);
            }
            return 0;
        }
    }

 // 페이징해서 게시글 목록 가져오기
    public List<Post> getPostsByPage(int page, int pageSize) throws SQLException {
        String sql = "SELECT * FROM posts ORDER BY created_at DESC LIMIT ? OFFSET ?";
        try (Connection conn = getConn();
                PreparedStatement pstmt = conn.prepareStatement(sql)) 
        {
            pstmt.setInt(1, pageSize);
            pstmt.setInt(2, (page - 1) * pageSize);
            ResultSet rs = pstmt.executeQuery();

            List<Post> posts = new ArrayList<>();
            while (rs.next()) {
                Post post = new Post();
                post.setId(rs.getInt("id"));
                post.setTitle(rs.getString("title"));
                post.setContent(rs.getString("content"));
                post.setCreatedAt(rs.getTimestamp("created_at"));
                // 필요한 필드 추가 세팅
                posts.add(post);
            }
            return posts;
        }
    }

    public Post getPostById(int id) throws SQLException {
        String sql = "SELECT * FROM posts WHERE id = ?";
        try (
                Connection conn = getConn();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {

            pstmt.setInt(1, id);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                Post post = new Post();
                post.setId(rs.getInt("id"));
                post.setTitle(rs.getString("title"));
                post.setContent(rs.getString("content"));
                post.setCreatedAt(rs.getTimestamp("created_at"));
                return post;
            }
            return null;
        }
    }

    public List<Post> getPosts(int offset, int limit) throws SQLException {
        List<Post> posts = new ArrayList<>();
        String sql = "SELECT * FROM posts ORDER BY created_at DESC LIMIT ? OFFSET ?";
        try (
                Connection conn = getConn();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {

            pstmt.setInt(1, limit);
            pstmt.setInt(2, offset);
            ResultSet rs = pstmt.executeQuery();
            while (rs.next()) {
                Post post = new Post();
                post.setId(rs.getInt("id"));
                post.setTitle(rs.getString("title"));
                post.setContent(rs.getString("content"));
                post.setCreatedAt(rs.getTimestamp("created_at"));
                posts.add(post);
            }
        }
        return posts;
    }

    public List<Post> getAllPosts() {
        List<Post> list = new ArrayList<>();
        String sql = "SELECT * FROM posts ORDER BY id DESC";

        try (Connection conn = getConn();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {

            while (rs.next()) {
                list.add(new Post(
                    rs.getInt("id"),
                    rs.getString("title"),
                    rs.getString("content"),
                    rs.getTimestamp("created_at")  // ← created_at 추가
                ));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public void addPost(String title, String content) {
        String sql = "INSERT INTO posts (title, content) VALUES (?, ?)";

        try (Connection conn = getConn();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, title);
            pstmt.setString(2, content);
            pstmt.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. JSP 수정하기 (list.jsp 예시)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*, model.Post" %>
<%
    List<Post> posts = (List<Post>) request.getAttribute("posts");
    int currentPage = (Integer) request.getAttribute("currentPage");
    int totalPages = (Integer) request.getAttribute("totalPages");

    int pageGroupSize = 10;
    int currentPageGroup = (int) Math.ceil((double) currentPage / pageGroupSize);
    int startPage = (currentPageGroup - 1) * pageGroupSize + 1;
    int endPage = Math.min(startPage + pageGroupSize - 1, totalPages);
%>

<html>
<head>
    <title>게시판 목록</title>
</head>
<body>
    <h2>게시판 목록</h2>

    <table border="1" width="600">
        <tr>
            <th>ID</th><th>제목</th><th>작성일</th>
        </tr>
        <%
            for (Post post : posts) {
        %>
        <tr>
            <td><%= post.getId() %></td>
            <td>
                <% int currPage = (request.getAttribute("currentPage") != null) ? 
                      (Integer) request.getAttribute("currentPage") : 1;
                 %>
                <a href="postView?id=<%= post.getId() %>&page=<%= currPage %>">
                <%= post.getTitle() %></a>
               </td>
            <td><%= post.getCreatedAt() %></td>
        </tr>
        <%
            }
        %>
    </table>

    <div class="pagination" style="margin-top:20px;">
        <% if (startPage > 1) { %>
            <a href="board?page=<%= startPage - 1 %>">&laquo; 이전</a>
        <% } %>

        <% for (int i = startPage; i <= endPage; i++) { %>
            <% if (i == currentPage) { %>
                <strong><%= i %></strong>
            <% } else { %>
                <a href="board?page=<%= i %>"><%= i %></a>
            <% } %>
        <% } %>

        <% if (endPage < totalPages) { %>
            <a href="board?page=<%= endPage + 1 %>">다음 &raquo;</a>
        <% } %>
    </div>
</body>
</html>