취업/CodeIgniter

[ci4] DataTable 서버-사이드 Server-side Processing

카슈밀 2022. 7. 15. 14:32
반응형

데이터 테이블을 구현하는데 있어 서버사이드 기능이 필요했다.

프론트만 쓰면 좋지만, 이게 5천개가 넘어간 순간 1분이 넘게 로딩된다...

 

그래서 이전에는 구현하지 못했지만, 이번에 구현하게 되었다.

아래 테이블 컬럼들은 의미 없는 데이터입니다.

// front.js
<script>
        $(document).ready( function () {
            $('#usertable').DataTable({
                order: ['1', 'desc'],
                processing: true,
                search: {
                    return: true,
                },
                serverSide: true,
                ajax: {
                    url: '/serverside',
                    type: 'POST',
                    "dataSrc": function(res){
                        let data = res.data;
                        return data;
                    },
                },
                "columns":[
                    {"data": 'idx'},
                    {"data": 'user'},
                    {"data": 'name'},
                ]
            });
        } );
        
    </script>

네트워크 통신시 전달되는 데이터 값.

draw: 3
columns[0][data]: 0
columns[0][name]: 
columns[0][searchable]: true
columns[0][orderable]: true
columns[0][search][value]: 
columns[0][search][regex]: false
columns[1][data]: 1
columns[1][name]: 
columns[1][searchable]: true
columns[1][orderable]: true
columns[1][search][value]: 
columns[1][search][regex]: false
columns[2][data]: 2
columns[2][name]: 
columns[2][searchable]: true
columns[2][orderable]: true
columns[2][search][value]: 
columns[2][search][regex]: false
columns[3][data]: 3
columns[3][name]: 
columns[3][searchable]: true
columns[3][orderable]: true
columns[3][search][value]: 
columns[3][search][regex]: false
columns[4][data]: 4
columns[4][name]: 
columns[4][searchable]: true
columns[4][orderable]: true
columns[4][search][value]: 
columns[4][search][regex]: false
columns[5][data]: 5
columns[5][name]: 
columns[5][searchable]: true
columns[5][orderable]: true
columns[5][search][value]: 
columns[5][search][regex]: false
order[0][column]: 0
order[0][dir]: asc
start: 0
length: 10
search[value]: ㄴㄹ // 검색시 자동으로 들어가진다.
search[regex]: false

 

controller단

public function serverside() {
        $columnName = htmlspecialchars($_POST['order'][0]['column']);
        $indexNumber = htmlspecialchars($_POST['order'][0]['dir']); // asc, desc
        $columnData = htmlspecialchars($_POST['columns'][$columnName]['data']);
        $columnOrderable = htmlspecialchars($_POST['columns'][$columnName]['orderable']);
        
        
        if ( $columnOrderable == 'true' ) {
            $dir = $indexNumber === 'asc' ? 'ASC' : 'DESC';
            $order = 'ORDER BY '. $columnData .' '. $dir;
        } else {
            $order = '';
        }

        $bindings = array();
        if ( isset($_POST['search']) && $_POST['search']['value'] != '' ) {
			$str = htmlspecialchars($_POST['search']['value']);
			for ( $i=0, $ien=count($_POST['columns']) ; $i<$ien ; $i++ ) {
				$requestColumn = htmlspecialchars($_POST['columns'][$i]['searchable']);
				if ( $requestColumn == 'true' ) {
                    $binding = "%".$str."%";
                    $globalSearch[] = "".htmlspecialchars($_POST['columns'][$i]['data'])." LIKE ".json_encode($binding);
				}
			}
            $where = 'WHERE ('.implode(' OR ', $globalSearch).')';
            if(!isset($where)) {
                $where = '';
            }
		} else {
            if(!isset($where)) {
                $where = '';
            }
        }


        // // 셀렉트 테이블 
        $data = model->tableMake($where, $order);
        $draw = $_POST['draw'];
        $start = $_POST['start'];
        $length = $_POST['length'];
        $list = array_slice($data, $start, $length); // limit 수;

        return json_encode(array(
            "draw"            => $draw, // 몇번째 테이블이 그려지는지.
            "recordsTotal"    => count($data), // 몇개의 전체 row인지
            "recordsFiltered" => count($data), // 얼마만큼 필터링 되었는지.
            "data"            => $list  // 데이터 덩어리.
        ));
    }

model 부분

public function tableMake($where, $orderBy)
    {
        $sql = "SELECT * FROM table $where $orderBy";
        // $sql 조회 후 해당 데이터를 result에 담아 반환.
        return $result;
    }

 

다 작성해서 작동은되는데, sql을 직접 들어가는 것이라 인젝션에 대한 공격 부분의 여지가 있어...

이부분을 어찌할지 고민중이다.

sql문 자체에 들어가는 게 원래는 지양해야하는데, 해당 부분이 문제가 되고 있다. 흠...대안은 고민해보고 수정해야지


참고 자료


공식 문서. 서버쪽 스크립트 자료가 있다.

실제로 제일 중요한 부분이 기술.

https://datatables.net/examples/server_side/simple.html

 

DataTables example - Server-side processing

Server-side processing There are many ways to get your data into DataTables, and if you are working with seriously large databases, you might want to consider using the server-side options that DataTables provides. With server-side processing enabled, all

datatables.net

php sql을 사용하는 실제 db값 가져오는 내장 기능 설명서

https://github.com/DataTables/DataTables/blob/f60c41290255c3fcab38999161f9529226b655c9/examples/server_side/scripts/ssp.class.php

 

GitHub - DataTables/DataTables: Tables plug-in for jQuery

Tables plug-in for jQuery. Contribute to DataTables/DataTables development by creating an account on GitHub.

github.com

 

마지막으로 기본적으로 줘야하는 값을 정리해주는 부분과 limit 부분을 구현하는데 참고한 자료.

이게 찾아보니 동일한 내용으로 다른 글도 있던데, 무엇이 원본인지는..모르겠다.

https://zamezzz.tistory.com/310

 

[JavaScript #11] dataTables 사용하기 (2)

● dataTables - 2 오늘은 지난 포스팅에 이어 dataTables의 server-side processing에 대해서 정리하겠습니다. 너무 많은 데이터 행을 처리할 때는 너무 느리고 모든 데이터를 다루기가 힘듭니다. 이를 해결

zamezzz.tistory.com

 

728x90