JavaScript

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

zamezzz 2019. 5. 8. 22:01

 dataTables - 2

 

오늘은 지난 포스팅에 이어 dataTables의 server-side processing에 대해서 정리하겠습니다.

 

너무 많은 데이터 행을 처리할 때는 너무 느리고 모든 데이터를 다루기가 힘듭니다.

 

이를 해결하기 위해서 제공해주는 방법이 바로 server-side processing입니다.

 

 Server-side processing paramter

 

server-side processing은 데이터를 그리기 위해 javascript에서 서버측으로 ajax 요청을 합니다.

 

서버에서는 이 ajax요청을 받아 해당하는 데이터만 다시 리턴해주게 됩니다.

 

그럼 먼저 서버로 보내는 파라미터 종류를 살펴보겠습니다.

 

- draw

  count. ajax요청에 의해 그려질 때 dataTable이 순차적으로 그려지는 것을 보장하기 위해 사용
- start
  페이징 첫번째 레코드 값
- length
  현재 페이지에 그려질 레코드 수
- search[value]
  전체 테이블 데이터 검색을 위한 변수 값
- search[regex]
  전체 테이블 데이터 검색을 정규 표현식으로 처리해야할 경우 사용 디퐅르 false
- order[i][column]
  ordering을 적용해야하는 컬럼
- order[i][dir]
  ordering 방향 (asc or desc)
- column[i][data]
  i번째 컬럼의 데이터 값
- column[i][name]
  i번째 컬럼명
- column[i][searchable]
  i번째 컬럼이 검색이 가능하게 할 것인지 플래그 (t/f)
- column[i][orderable]
  i번째 컬럼이 ordering이 가능하게 할것인지플래그 (t/f)
- column[i][search][value]
  i번째 컬럼의 검색을 위한 변수 값
- column[i][search][regex]
  i번째 컬럼의 검색을 정규 표현식으로 처리할 경우 사용 (false)

 

다음은 리턴되는 파라미터입니다.

- draw
  요청하는 draw와 같은 의미입니다. count
- recordsTotal
  필터링 전 전체 레코드 수
- recordsFiltered
  필터링 후 전체 레코드 수
- data
  테이블에 그릴 데이터 (array)
- error
  error 발생 시 표시할 메시지 (optional)

 

 Server-side processing example

 

이제 실제 사용방법에 대해 예제를 보겠습니다.

 

먼저 html 코드입니다. 별도 데이터를 가져올 필요가 없어 매우 단순해졌습니다.

 

<tbody>부분이 사라졌습니다.

<table id="exampleTable" class="table table-bordered">

  <thead>

    <tr>

      <th>Seq</th>

      <th>Name</th>

      <th>Age</th>

      <th>Date</th>

    </tr>

  </thead>

</table>

 

다음은 js코드입니다. 몇 개의 옵션이 추가되었지만, 그래도 매우 간단합니다.

 

serverside 옵션과 processing 옵션이 추가되었습니다.

$("#exampleTable").DataTable({

    "serverSide": true,
    "processing": true,
    "ajax": {
        "url": "/example",
        "type": "POST",
        "dataSrc": function(res) {
            var data = res.data;
            return data;
        }
    },
    "columns" : [
        {"data": "seq"},
        {"data": "name"},
        {"data": "age"},
        {"data": "date"},
    ]

});

 

필요한 option을 사용했고, "/example" 로 ajax 요청을 하여 dataSrc를 받아옵니다. 

 

그리고 이를 columns으로 넣는 간단한 코드입니다.

 

이제 server 코드를 보겠습니다. 먼저 리턴 데이터를 위한 dto를 구성하겠습니다.

 

return paramters와 같은 모양으로 구현하면 됩니다.

@Data
public class DataTableDto {
    private int draw;
    private int recordsTotal;
    private int recordsFiltered;

    private List data;

    public List getData(){
        if(CollectionUtils.isEmpty(data)){
            data = new ArrayList();
        }
        return data;
    }

}

 

dto를 생성하였으면 이를 이용해 이제 service 로직은 구현해야 합니다.

 

jpa를 사용하는걸로 생각하여 간단하게 구현한 서비스 코드입니다.

@PostMapping(value = "/example")
@ResponseBody
public DataTableDto example(DataTableDto dto, @RequestBody MultiValueMap<String, String> formData){
    int draw = Integer.parseInt(formData.get("draw").get(0));
    int start = Integer.parseInt(formData.get("start").get(0));
    int length = Integer.parseInt(formData.get("length").get(0));

    int total = (int)exampleRepository.count();
    List data = exampleRepository.findData(start, length);

    dto.setDraw(draw);
    dto.setRecordsFiltered(total);
    dto.setRecordsTotal(total);
    dto.setData(data);

    return dto;
}

 

request parameter인 formData는 위에서 설명한 ajax 요청 시 서버로 보내는 파라미터 입니다.

 

여기서 필요한 draw, start, length만 꺼내어 사용했습니다.

 

그리고 DB에서 데이터를 조회하였고, 이를 dto로 다시 조립하여 리턴해줍니다.

 

이를 실행시키면 아래와 같은 테이블이 완성됩니다.

 

이렇게 하면 dataTables의 server-side processing 구현이 완료되었습니다.

 

동적으로 필요한 데이터만 가져와 그려주기 때문에 좋은 성능을 가집니다.

 

하지만 search를 위해서는 추가 구현을 해주어야 합니다. 기본 search는 현재 데이터만을

 

대상으로 제공하기 때문입니다.

 

 

 Server-side processing search

 

search를 위해서는 추가로 몇 개의 파라미터를 더 사용해야 합니다.

 

위의 파라미터에서 살펴보았던 search[value] 를 사용하면 전체 검색이 가능합니다.

 

하지만 column별 검색을 제공하고 싶다면 아래 2개의 파라미터를 사용해야 합니다.

- column[i][searchable] 
- column[i][search][value] 

 

그렇다면 검색을 위해 사용되는 주요 파라미터는 총 5개입니다.

 

draw, start, length, column[i][searchable], column[i][search][value]

 

이 5개를 이용하여 검색예제를 구현해보겠습니다.

 

먼저 검색창 부터 만들어야합니다. 기존 검색창은 따로 컬럼이 구분되어 있지 않아요.

 

그래서 먼저 기본 검색창에 hidden 옵션을 주어 숨기고, 간단한 검색창을 만들었습니다.

 

검색창 hidden 옵션은 이렇게 하시면 됩니다. $("#exampleTable_filter").attr("hidden", "hidden");

 

그리고 커스텀한 검색창은 기호에 맞게 구현하시면 됩니다. 저는 select box를 이용하였습니다.

 

column[i]의 순서대로 0은 seq, 1은 name, 2는 age, 3은 date로 설정하였습니다.

그리고 위 search 버튼의 클릭이벤트는 아래와 같이 작성합니다.

$("#searchBtn").click(function () {
    var numCols = table.columns().nodes().length;
    for(var i=0; i<numCols; i++) { table.column(i).search(''); }

    var searchType = $("#searchType").val();
    var searchValue = $("#searchValue").val();

    table.column(searchType).search(searchValue).draw();
})

 

처음 2줄은 table을 init하는 과정입니다. 기존 검색으로 table의 파라미터에 설정된 다른

 

검색 파라미터 값을 초기화시키는 작업입니다.

 

그리고 dataTable의 search() API를 이용하여 searchType과 searchValue를 서버로 전달합니다.

 

예를 들어 name을 'AAA'로 search를 실행하고 서버에서 전달받은 formData를 log로 찍어보면

 

아래와 같은 모습입니다. 

{
draw=[1], 
columns[0][data]=[seq], columns[0][name]=[], columns[0][searchable]=[true], columns[0][orderable]=[false], columns[0][search][value]=[], columns[0][search][regex]=[false], 
columns[1][data]=[name], columns[1][name]=[], columns[1][searchable]=[true], columns[1][orderable]=[false], columns[1][search][value]=[AAA], columns[1][search][regex]=[false], 
columns[2][data]=[age], columns[2][name]=[], columns[2][searchable]=[true], columns[2][orderable]=[false], columns[2][search][value]=[], columns[2][search][regex]=[false], 
columns[3][data]=[date], columns[3][name]=[], columns[3][searchable]=[true], columns[3][orderable]=[false], columns[3][search][value]=[], columns[3][search][regex]=[false], 
start=[0], length=[10], search[value]=[], search[regex]=[false]
}

 

중간의 columns[1][search][value]=[AAA]가 보이시나요 ?

 

저희가 검색을 위해 사용해야 할 파라미터입니다.

 

String nameParam = formData.get("columns[1][search][value]").get(0);

 

이러한 방식으로 파싱해서 사용하면 됩니다. 그리고 이 변수를 통해 DB셀렉트를 하고

 

필요한 데이터를 리턴해주면 됩니다. 

int total;
List data;


if(nameParam.lenght() > 0) {
    total = (int)exampleRepository.countByName(nameParam);
    data = exampleRepository.findDataByName(nameParam, start, length);
} else {
    total = (int)exampleRepository.count();
    data = exampleRepository.findData(start, length);
}

 

위의 코드를 실행하고 'AAA'를 검색해보면 아래와 같은 결과를 얻을 수 있습니다.

 

 

그리고 필요에 따라서는 multiple search를 할 수 있고 Like 검색 또한 할 수 있습니다.

 

쿼리만 조금 복잡할 뿐 변수를 받아 쿼리를 작성하고 가공한 후 해당 데이터를 리턴해주면

 

되는 모두 동일한 로직입니다. 

 

그럼 dataTables의 server-side processing과 search 에 대한 정리를 마치겠습니다.

 

감사합니다.

반응형