반응형
웹 애플리케이션에서 게시판, 상품 목록, 검색 결과 등 많은 데이터를 다룰 때는 한 페이지에 모든 항목을 출력하는 것보다, 일정 개수씩 나눠서 보여주는 페이징 처리가 필요합니다. 이 글에서는 PHP로 구현한 페이징 처리 예제를 기반으로, 각 부분의 동작 원리와 구현 포인트를 설명합니다.
전체 코드 샘플
<?php
# Getting Parameter And Default Variable Setting ###############################
$page_now = $_GET['page_now'];
$page_row = $_GET['page_row'];
$total_search = $_GET['total_search'];
# Parameter to Query Processing ################################################
if ($total_search)
{
$tmp_search = explode(" ", $total_search);
foreach ($tmp_search as $k=>$v)
{
$ARR_SRCH_SQL[] = "board_subject like '%{$v}%'";
$ARR_SRCH_SQL[] = "strip_tags(board_content) like '%{$v}%'";
}
$ARR_SRCH_SQL = implode(" or ", $ARR_SRCH_SQL);
$SRCH_SQL .= " AND ({$ARR_SRCH_SQL})";
}
# List SQL Query ###############################################################
$page_num = 10;
$page_row = $page_row != null ? $page_row : 20;
$page_now = $page_now != null ? $page_now : 0;
$offset = $page_now * $page_row;
$total_row = (int) $db->get_var("SELECT COUNT(*) FROM board WHERE 1 = 1 {$SRCH_SQL}");
$total_page = (int) ceil($total_row / $page_row);
$list_sql = "SELECT * FROM board WHERE 1 = 1 {$SRCH_SQL} ORDER BY board_pk DESC LIMIT {$offset}, {$page_row}";
$res_sql = $db->get_results($list_sql);
# Create HTML ##################################################################
if ($res_sql)
{
foreach ($res_sql as $data)
{
$HTML .= "
<tr>
<td>{$data->board_pk}</td>
<td>{$data->board_subject}</td>
<td>{$data->board_write_date}</td>
</tr>
";
}
}
?>
<form name='frm' action='<?=$_SERVER['PHP_SELF']?>' method='get' class='frm' id='frm'>
<input type='hidden' name='page_now' value='<?=$page_now?>' />
<input type="text" name='total_search' value='<?=$total_search?>'>
<button type='submit'>검색</button>
<?=$HTML?>
<div class="paginate">
<?php
$paginate_html = '';
if ($total_row > 0) {
// Prev 버튼
$paginate_html .= "<a href=\"javascript:goList('0')\">Prev End</a>";
if ($page_now > 0) {
$paginate_html .= "<a href=\"javascript:goList(" . ($page_now - 1) . ")\"> Prev </a>";
}
// 페이지 블록 계산
$half_block = (int) floor($page_num / 2);
if ($total_page <= $page_num) {
$start = 0;
$end = $total_page;
} elseif ($page_now <= $half_block) {
$start = 0;
$end = $page_num;
} elseif ($page_now >= $total_page - $half_block) {
$start = $total_page - $page_num;
$end = $total_page;
} else {
$start = $page_now - $half_block;
$end = $page_now + $half_block;
}
// 페이지 번호 출력
for ($i = $start; $i < $end; $i++) {
$display = $i + 1;
if ($i == $page_now) {
$paginate_html .= "<strong>{$display}</strong>";
} else {
$paginate_html .= "<a href=\"javascript:goList({$i})\">{$display}</a>";
}
}
// Next 버튼
$last_page = $total_page - 1;
if ($page_now < $last_page) {
$paginate_html .= "<a href=\"javascript:goList(" . ($page_now + 1) . ")\"> Next </a>";
}
$paginate_html .= "<a href=\"javascript:goList('{$last_page}')\">Next End</a> ";
} else {
$paginate_html .= "<a href=\"javascript:goList(0)\"> Prev End</a>";
$paginate_html .= "<a href=\"javascript:goList(0)\"> Prev </a>";
$paginate_html .= "<strong>1</strong>";
$paginate_html .= "<a href=\"javascript:goList(0)\"> Next </a>";
$paginate_html .= "<a href=\"javascript:goList(0)\"> Next End</a>";
}
echo $paginate_html;
?>
</div>
<script type="text/javascript">
function goList(page)
{
var f=document.frm;
f.page_now.value=page;
f.submit();
}
</script>
<style>
.paginate {
display: flex;
justify-content: center;
align-items: center;
margin: 20px 0;
}
.paginate a,
.paginate strong{border: 1px solid #ccc; padding: 5px 10px; margin: 0 5px; text-decoration: none; color: #333;}
.paginate strong{
background-color: #007bff;
color: #fff;
}
</style>
</form>
1. 파라미터 수집 및 초기값 설정
$page_now = $_GET['page_now'];
$page_row = $_GET['page_row'];
$total_search = $_GET['total_search'];
- page_now: 현재 페이지 번호
- page_row: 한 페이지에 출력할 게시글 수 (기본값 20)
- total_search: 검색 키워드
2. 검색 조건 처리
if ($total_search)
{
$tmp_search = explode(" ", $total_search);
foreach ($tmp_search as $v)
{
$ARR_SRCH_SQL[] = "board_subject like '%{$v}%'";
$ARR_SRCH_SQL[] = "strip_tags(board_content) like '%{$v}%'";
}
$ARR_SRCH_SQL = implode(" or ", $ARR_SRCH_SQL);
$SRCH_SQL .= " AND ({$ARR_SRCH_SQL})";
}
- 검색어가 존재할 경우, 제목과 내용에서 해당 키워드를 포함하는 조건을 SQL에 추가합니다.
- 다중 키워드 지원을 위해 공백 기준으로 분할하고 LIKE 검색을 반복 적용합니다.
3. 페이징 변수 계산
$page_num = 10;
$page_row = $page_row != null ? $page_row : 20;
$page_now = $page_now != null ? $page_now : 0;
$offset = $page_now * $page_row;
- $offset: LIMIT 절에 사용될 시작 위치 계산
- $page_num: 한 번에 보여줄 페이지 수 (예: 1~10)
4. 전체 게시물 수 조회 및 페이지 계산
$total_row = (int) $db->get_var("SELECT COUNT(*) FROM board WHERE 1 = 1 {$SRCH_SQL}");
$total_page = (int) ceil($total_row / $page_row);
- 전체 행 수를 구한 뒤, 페이지 수를 계산합니다.
5. 데이터 조회 및 리스트 생성
$list_sql = "SELECT * FROM board WHERE 1 = 1 {$SRCH_SQL} ORDER BY board_pk DESC LIMIT {$offset}, {$page_row}";
$res_sql = $db->get_results($list_sql);
- 지정된 조건과 오프셋, 제한 수에 따라 게시글을 조회합니다.
6. 페이징 HTML 출력
// Prev / Next 버튼, 페이지 번호 계산
$half_block = floor($page_num / 2);
- 현재 페이지 위치에 따라 시작 번호와 끝 번호를 조절하여 페이징 블록을 유동적으로 구성합니다.
- Prev, Next, 처음/끝으로 이동하는 버튼을 포함합니다.
7. HTML 출력 및 폼
<form name='frm' action='<?=$_SERVER['PHP_SELF']?>' method='get'>
<input type='hidden' name='page_now' value='<?=$page_now?>'>
<input type='text' name='total_search' value='<?=$total_search?>'>
<button type='submit'>검색</button>
</form>
- 검색 폼과 페이징 파라미터를 유지하기 위한 hidden input 활용
- 페이지 이동은 JavaScript 함수 goList()를 통해 처리됨
function goList(page) {
var f = document.frm;
f.page_now.value = page;
f.submit();
}
8. 스타일링
.paginate {
display: flex;
justify-content: center;
margin: 20px 0;
}
.paginate a,
.paginate strong {
border: 1px solid #ccc;
padding: 5px 10px;
margin: 0 5px;
text-decoration: none;
color: #333;
}
.paginate strong {
background-color: #007bff;
color: #fff;
}
- 현재 페이지 강조와 기본 스타일 적용을 통해 UX 향상
마무리
이 예제는 페이징 처리의 기본을 반영한 코드입니다.
- 검색 조건 처리
- 동적 페이지 블록 계산
- JavaScript 연동
을 통해 유저 친화적인 인터페이스를 만들 수 있습니다.
실제 프로젝트에서는 SQL 인젝션 방지, XSS 필터링, 페이지 범위 제한 등을 추가로 고려해야 합니다.
반응형
'Programing' 카테고리의 다른 글
| 엑셀/스프레디시트에서 숫자를 한글로 표기하는 방법 총정리 (Excel to Hangul Conversion) (4) | 2025.06.11 |
|---|---|
| 개발 중 자주 만나는 CORS 오류와 해결법 정리 (CORS Error in Web Development) (0) | 2025.06.10 |
| 리팩토링의 원칙과 사례 (Refactoring) (0) | 2025.06.02 |
| 웹 성능 측정 지표 (LCP, FID 등)과 JS 최적화 방법 (0) | 2025.04.29 |
| 브라우저 렌더링 최적화를 위한 비동기 패턴 정리 (1) | 2025.04.29 |
| Form 입력 유효성 검사 및 실시간 피드백 구현 가이드 (0) | 2025.04.29 |
| 퍼센트 계산, 백분율 계산 방식 (0) | 2015.06.11 |
| PHP, MySQL 및 Google 지도를 사용하여 매장 검색기 만들기 (0) | 2012.06.13 |