페이징이란?
많은 수의 자료(레코드)를 한꺼번에 가져와 활용하기에는 비효율적이기에 일정 크기로 나누어 페이지 번호를 부여하는 방법을 방법을 말한다.
즉, 원하는 페이지번호에 해당하는 영역의 자료만 가져와 활용하기 위함이다.
페이징을 하기전에 몇가지 사전 설정을 해야한다.
- 한페이지에 몇개의 레코드(자료)를 출력할 것인가?
- 한화면에 페이지번호를 몇개를 출력할 것인가?
- 현재 보고자 하는 페이지가 몇번째 페이지인가?
- 가져올 시작 레코드 번호
- 가져올 마지막 레코드 번호
- 전체 페이지 갯수
- 페이지번호 출력 시작 번호
- 페이지번호 출력 마지막 번호
- 전체 레코드 갯수
- 전체 블록 갯수
- 현재 속해있는 블록 번호
- $page_per_record = 10; //화면에 표시할 자료 갯수(페이지당 레코드수)
- $block_per_page = 5; //화면에 표시할 페이지 번호 갯수(블록당 페이지수)
- $now_page = 7; //현재 선택된 페이지 번호(GET,POST등 외부로 부터 넘어온다.)
- $total_record = 122; //전체 레코드수는 DB를 통해 얻어온다.
- $total_page = ceil($total_record / $page_per_record); //전체 페이지 갯수
- $total_block = ceil($total_page / $block_per_page); //전체 블록 갯수
- $now_block = ceil($now_page / $block_per_page); //현재 페이지가 속해 있는 블록 번호
- $start_record = (($now_page-1) * $page_per_record) + 1; //가져올 레코드 시작 번호
- $start_page = (($now_block-1) * $block_per_page) + 1; //가져올 페이지 시작 번호
- $total_page = ceil(122 / 10); //출력 13, 전체페이지 갯수
- $total_block = ceil(13 / 5); //출력 3, 전체 블록 갯수
- $now_block = ceil(7 / 5); //출력 2, 현재 7페이지가 위치한 블록 번호
- $start_record = ((7-1) * 10)+1; //출력 61, 가져올 레코드 번호
- $start_page = ((2-1) * 5)+1; //출력 6, 가져올 페이지 번호
- DB문: "SELECT * FROM table_name WHERE 조건절 LIMIT $start_record, $page_per_record"
- $end_page = ( ($start_page+$block_per_page) <= $total_page )? ($start_page+$block_per_page) : $total_page;
- 페이지번호: "for($i = $start_page; $i <= $end_page; $i++)" 이런 형태로 이용하면 된다.
- if( $now_page > 1 ) { //이전페이지 링크 출력; }
- if( $now_page < $total_page ) { //다음페이지 링크 출력; }
- if( $now_block > 1 ) { //이전 블록 링크 출력; }
- if( $now_block < $total_block ) { //다음 블록 링크 출력; }
- if( $now_block > 2 ) { //앞 블록이 2블록 이상 차이날경우 처음으로 링크 출력; }
- if( $now_block < ($total_block-1) ) { //남은 블록이 2블록 이상인 경우 마지막으로 링크 출력; }
그리고 아래와 같은 항목이 필요하다.
등등을 계산해야 한다.
위에서 블록 개념을 알아야 하는데, 아래 그림을 보자.
전체 페이지 갯수가 13개일경우 한 페이지당 5개의 페이지 번호를 보여준다고 하면, 총 3개의 묶음으로 나누어 지는데, 이묶음을 페이지 블록이라고 하는데 이후로는 블록이라 이야기 하겠다.
우리가 전체 자료에서 원하는 페이지영역의 자료만 가져오기 위해서는 해당자료가 몇번째에 위치해 있는지 확인해야 할 필ㅇ가 있다. 끝나는 위치는 페이지당 몇개씩 보여줄것인가 정했기 때문에 그 갯수 만큼만 가져오면 된다.
만약, 다른 페이지를 선택하거나, 현재 목록에 없는 페이지 번호로 넘어가고자 한다면 자료의 가져올 위치뿐만 아니라 페이지번호를 출력할 시작번호와 끝번호도 필요하게 된다.
<이전> 5 6 7 8 9 10 <다음>
위와 같은 예를 보자면 한화면에 5개의 페이지 번호를 보여준다고 할때, 다음 버튼을 누르면 10번 이후의 번호부터 5개 이내의 페이지 번호를 보여주게 된다. 5개 이내라고 이야기하는 이유는 페이지 번호가 13번호까지만 있을수 있기 때문이다.
여기에서 현재 블록은 2번째이고, 이전을 선택하면 1번째 블록으로, 다음을 선택하면 3번째 블록으로 이동하게 된다.
각 블록으로 이동되었을때 블록에 해당하는 시작 페이지 번호와 끝나는 페이지 번호를 구하고, 선택된 페이지 번호에 따른 시작 레코드 번호와 끝나는 레코드 번호를 구해야 하는것이다.
우선 각 항목을 PHP 변수로 정의를 해보자.
페이지당 레코드수나, 블록당 페이지수는 사용자가 출력을 원하는 만큼 결정을 하면된다. 추후에도 이 수치값만 바꾸면 한번에 자료를 10개씩 보여주거나, 50개씩 보여주는등 쉽게 변경이 가능하고, 페이지 번호도 기본 5개 이지만, 10개나 20개등 마음대로 변경이 가능하다.
그리고, 페이지 번호선택은 처음 선택되지 않은경우는 대부분 1이나 마지막 페이지 번호를 선택하는 경우가 많고, 정상적인 데이터가 넘어오는가 확인은 여기에서는 다루지 않겠다. 적정한 페이지 번호로 선택된걸로 간주한다.
전체 레코드수는 보통 정해져있지 않고 자료를 가져오는 시점 DB에 있는 전체갯수를 대상으로 하기때문에 대부분 현재 DB에 전체 자료갯수를 가져오는 질의문을 통해 값을 얻어온다.
그럼 본격적으로 필요한 자료를 구해보자.
우선 시작 페이지 번호와 시작 레코드번호를 구하기 위해서는 아래와 같은 값들은 먼저 구해야 한다.
위에서 최종적으로 필요한 항목은 DB에서 원하는 위치의 자료를 가져오기 위한 $start_record와 페이지번호 링크를 출력하기 위한 $start_page 항목일 것이다.
끝나는 위치는 레코드의 경우는 "레코드 시작번호 + 페이지당 레코드수 -1"을 하면 나오지만, LIMIT 절에서 이용할 경우, "LIMIT 레코드 시작번호, 가져올 레코드 갯수" 이므로 가져올 레코드 끝번호를 넣으면 엉뚱한 결과를 가져온다.
위 내용을 하나씩 알아보자.
우선 페이지 번호와 블록번호는 1부터 시작함을 기억하자. 0부터 시작하는것이 수식상에서는 조금 짧아지기는 하지만 접근할때는 헷갈리고, 실제 표시되는 페이지 번호와 내부에서 처리되는 페이지 번호가 달라지기때문에 혼동이 생긴다.
먼저 전체 자료를 10개씩 보여주기로 했기때문에 총 몇개의 페이지가 생기는지 확인할 필요가 있다. 즉, 전체 자료갯수에서 페이지당 레코드 갯수로 나누어주면 구할수가 있다.
122 / 10 = 12.2
그러나 위와 같이 소수점이 발생되는 경우 자투리가 남는경우 인데, 이경우 자투리도 페이지 번호가 필요하므로 올림처리를 해주어야 한다. 즉, 총 12개가 아니라 13개의 페이지가 필요하기 때문이다.
여기에서 PHP 함수인 ceil()함수를 사용했는데 바로 소수점 올림 함수이다.
float ceil ( float $value);
전체 블록 갯수와 현재 속한 블록 번호를 구하는 이유는 자료를 출력후 다른 자료목록 이동을 위한 페이지번호를 출력할 경우 출력할 페이지 시작번호와 끝번호를 구하기 위함이다. 위 그림을 보면 이해가 쉬울것이다.
위 예제값으로 값을 구해본다면, (현재 7페이지 선택, 전체자료 122개, 레코드 10개씩, 페이지번호 5개씩 출력)
위에서 구한 항목을 가지고 DB에서 자료를 가져오고, 페이지 번호 출력을 하면 완성이다.
다만 DB에서 질의를 할경우에는 처음에 전체 레코드 갯수를 가져오는 질의문의 조건문과 동일해야 함을 잊지 말자!
그리고 페이지 번호 출력외에 이전페이지, 다음페이지, 이전 페이지 블록, 다음 페이지 블록등 페이지 블록자체를 넘어가는 경우가 필요하다. 이런경우 조건을 따져가면서 해당 요건이 되는경우 출력을 해주면 된다.
예를보자.
위 조건을 응용해서 현재 출력 페이지 번호 이외의 페이지 블록으로 이동하는 링크 출력이 가능할 것이다.
페이징 기법은 수 많은 방법들이 있습니다. 이 예제는 제가 쓰는 방법 위주로 설명을 한것이니 필요하신분 참고하세요.