[9. 비회원게시판 - 게시글목록]

Minseok Jo·2025년 9월 11일
post-thumbnail

개발 대상은 [비회원게시판 - 게시글목록] 페이지이다.
구성은 다음과 같다.

free_list.php : 게시글 목록 출력 페이지
free_list.js : 게시글 정렬 관련 Javascript
board_list.js : 게시글 목록 출력 CSS


1. Frontend & Backend

<free_list.php>

<?php
    include "../db/db_con.php";
    date_default_timezone_set("Asia/Seoul");


    $sql = "select count(*) as total from freeboard";
    $result = mysqli_query($con, $sql);
    $_result = mysqli_fetch_assoc($result);
    $count = $_result["total"];

    $limit = 5;

    $total_page = ceil($count/$limit);

    if(!isset($_GET['page']) or !ctype_digit($_GET['page']))
        $page = 1;
    else
        $page = $_GET["page"];


    if (($page<1) or ($page > $total_page))
        $page = 1;

    $offset = ($page-1)*$limit;

    if (!isset($_GET["order"]))
        $order = "num";
    else
        $order = $_GET["order"];

    if ($order != "views")
        $order = "num";

    $sql = "select * from freeboard
            order by $order desc limit $limit offset $offset";
    $result = mysqli_query($con, $sql);
?>

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>자유 게시판</title>
        <script src="../js/free_list.js?v=<?=time()?>"></script>
        <link rel="stylesheet" href="../css/board_list.css?v=<?=time()?>">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"/>
    </head>
    <body>
        <?php include "../include/header.php"; ?>
        <h2><i class="fa-solid fa-comments"></i> 자유 게시판</h2>
        <form method="get" action="./free_search.php">
            <select id="input_select" name="input_select">
                <option value="title">제목</option>
                <option value="writer">작성자</option>
            </select>
            <input id="input_search" name="input_search" placeholder="검색어 입력" size="80">
            <input type="submit" value="검색">
        </form>
        <select id="order">
            <option value="recent" <?= ($_GET['order'] ?? '') == 'recent' ? 'selected' : '' ?>>최신순</option>
            <option value="views" <?= ($_GET['order'] ?? '') == 'views' ? 'selected' : '' ?>>조회순</option>
        </select>

        <table>
            <?php
            if (mysqli_num_rows($result)>0) {
                echo "<tr>";
                echo "<th>No.</th>";
                echo "<th width='800'>제목 <i class='fa-solid fa-book'></i></th>";
                echo "<th>작성자 <i class='fa-solid fa-user-pen'></i></th>";
                echo "<th>날짜 <i class='fa-solid fa-calendar-days'></i></th>";
                echo "<th>조회 <i class= 'fa-solid fa-eye'></i></th>";
                echo "</tr>";

                while ($row = mysqli_fetch_assoc($result)) {
                    $today_date = date("Y-m-d");
                    $write_day = substr($row['write_time'], 0, 10);

                    if ($write_day == $today_date)
                        $display_time = date("H:i", strtotime($row['write_time']));
                    else
                        $display_time = $write_day;

                    echo "<tr onclick=\"location.href='free_view.php?num={$row['num']}'\" style='cursor:pointer'>";
                    echo "<td>{$row['num']}</td>";
                    echo "<td>{$row['title']}</td>";
                    echo "<td>{$row['writer']}</td>";
                    echo "<td>{$display_time}</td>";
                    echo "<td>{$row['views']}</td>";
                    echo "</tr>";
                }
            }
            else {
                echo "<tr><td colspan='6' class='no-posts'>등록된 글이 없습니다.</td></tr>";
            }
            ?>
        </table>
        <div>
            <?php
            for ($i=1;$i<=$total_page;$i++) {
                if ($i == $page)
                    echo "<b>[{$i}]</b> ";
                else
                    echo "<a href='free_list.php?page={$i}&order={$order}'>$i</a> ";
            }
            ?>
        </div>
        <input type="button" onclick="location.href='./free_write.php'" value="게시글 작성">
    </body>
</html>

free_list.php

[1. 페이지 인덱스 계산]

  • 1. 전체 게시글 개수 계산
    "select count(*) as total from freeboard" SQL쿼리문을 실행하여 $count 변수에 전체 게시글의 개수를 저장한다.

  • 2. 페이지 당 최대 출력 게시글 개수 지정
    $limit 변수에 '페이지 당 최대 출력 게시글 수' 를 지정한다. 적당하게 5개를 지정하여, 페이지당 5개의 게시글이 출력되도록 하였다.

  • 3. 페이지 개수 계산
    전체 게시글 개수(count) / 페이지당 출력 게시글 수(limit) 를 한 결과에 천장함수를 적용하면, 필요한 페이지의 개수(page) 개수를 구할 수 있다.
    → 만약 전체 게시글 개수(13개), 페이지당 출력 게시글 수(5개)라면 (13/5) = ceil(2.6) = 3 이므로 전체 게시글을 출력하는데 필요한 페이지의 수는 3개가 된다.

  • 4. 페이지별 offset 계산
    offset은 페이지별로 몇번째 게시글부터 출력하면 되는지를 지정하는 값이다.
    (page-1)×limit 를 해서 나온값이 offset이 된다.
    → 만약 2번째 페이지에 출력되는 게시글 번호를 구하고 싶으면 page=2, limit=5이므로 (2-1)×5=5가 된다. 따라서 5번째 게시글 이후인 6번째 게시글부터 출력하도록 하면 된다.


[2. 게시글 출력]

  • 1. 테이블에서 게시글 검색:
    1에서 구한 offset 값을 바탕으로 테이블에서 해당 페이지 값에 맞는 게시글들을 검색한다. ("select * from freeboard order by $order desc limit $limit offset $offset")

  • 2. 검색 결과값들을 순서대로 처리
    limit값이 5이므로, offset값 이후의 5개의 게시글에 대한 검색결과가 mysqli_num_rows($result)에 담겨져 있다. while()문을 사용하여 게시글 필드를 하나씩 가져오며 그 결과를 테이블 형식으로 출력한다.

  • 3. 게시판 출력:
    테이블의 Head는 게시글 번호, 제목, 작성자, 날짜, 조회수 순으로 출력된다.

    날짜의 경우, 금일 작성된 글이면 작성 시간으로 표시되며 자정이 지난 게시글의 경우 작성 날짜로 표시된다.

    테이블의 각 행은, 클릭시 게시글 번호와 함께 free_view.php 로 이동되어 게시글의 내용을 확인할 수 있다.


[3. 게시글 정렬]

  • 최신순 / 조회수 기준에 따라 게시글 정렬:
    게시글 리스트의 Select 상자를 통해 게시글의 정렬 방식을 지정할 수 있다.
    사용자가 선택하는 값은 order 파라미터에 담겨 GET방식으로 전달된다.
    → 이 값이 order by 구문에 들어가게 되며, 게시글의 정렬 순서를 바꿀 수 있다.

    해당 동작을 처리하는 코드는 free_list.js에 스크립트로 작성되어 있다.

[4. 게시글 검색]

  • 검색어 입력:
    게시글 리스트의 검색어 입력칸을 통해 특정 조건의 게시글을 검색할 수 있다.
    제목/작성자, 검색어를 검색하면 해당 값이 input_select 와 input_search 파라미터에 담겨 GET방식으로 free_search.php에 전달된다.
    → 검색 결과는 free_search.php에서 처리한다.

[5. 페이지 인덱싱]

  • 페이지 이동:
    게시판 리스트 하단의 페이지 번호를 클릭하면 해당 페이지로 이동할 수 있다.
    각 페이지별로, page번호와 order를 전달함으로써 해당 페이지에 맞는 게시글 목록으로 이동할 수 있도록 하였다.

2. Javascript

<free_list.js>

document.addEventListener("DOMContentLoaded", function() {
    const select = document.getElementById("order");
    const params = new URLSearchParams(window.location.search);
    const page = params.get("page");
    const order = params.get("order");

    select.addEventListener("change", function() {
        location.href = "./free_list.php?page="+page+"&order="+ this.value;
    });
});
  • 최신순 / 조회수 정렬방식 선택시 해당 결과로 출력:
    사용자가 select 태그에서 정렬순서를 선택시, 이벤트리스너가 이름 감지하여 해당 기준에 맞는 정렬 결과로 리스트를 다시 출력한다.

    GET메소드를 통해 파라미터를 전달받으며 order값은 정렬기준을 나타내며, page 파라미터는 정렬결과 페이지에서도 이전의 페이지 번호를 유지할 수 있도록 해준다.

3. 동작 정리

게시글 목록 페이지 기본 화면



게시글 클릭시 (영상)



기능1: 페이징 (영상)



기능2: 정렬 (영상)



기능3: 검색 (영상)

0개의 댓글