본문 바로가기

Spring Boot

스프링부트 검색, 페이징처리 하기 Pageable

오늘은 검색 기능과 페이징 처리에 대해서 포스팅해보겠다

90프로 정도 완성했는데 완성 못한 게 있다 

각 페이지에 대한 부분을 동적으로 바꾸고 싶은데 어떻게 해야 할지 모르겠다ㅜㅜ

이건 천천히 다시 찾아보고, 오늘은 일단 구현한 기능들을 얘기해보겠다

까먹기 전에 기록!

 

1. 검색

2. 페이징 처리

3. 검색 페이지에서 페이징

 

이 세 가지를 다룰 예정이다

3번의 같은 경우는 검색을 하면 검색 결과가 많을 경우에 대한 페이징 처리이다

 

그럼 바로 시작

 

1. 검색

 

1-1 Repository

public interface BoardRepository extends JpaRepository<Board, Long> {

    List<Board> findByTitleContaining(String keyword);

}

 

JpaRepository에서 메서드명의 By이후는 SQL의 where 조건 절에 대응되는 것인데, 이렇게 Containing를 붙여주면 Like검색이 가능해진다

 

1-2 Service

 @Transactional
    public List<Board> search(String keyword) {

        List<Board> boardList = boardRepository.findByTitleContaining(keyword);

        return boardList;
    }

 

서비스 파일에서 search메서드를 구현해주었다

 

1-3 Controller

@GetMapping("/board/search")
    public String search(String keyword, Model model) {

        List<Board> searchList = boardService.search(keyword);

        model.addAttribute("searchList", searchList);

        return "search/searchPage";
    }

 

필자의 경우는 검색을 하게 되면 URL을 /board/search로 이동시킨 후 검색 리스트들을 뿌려주게 하고 싶었다

이에 맞는 뷰 페이지를 만들어 주자

 

1-4 searchPage.mustache

{{>layout/header}}

<table class="table">
    <thead class="thead-light">
    <tr>
        <th scope="col">#</th>
        <th scope="col">제목</th>
        <th scope="col">작성자</th>
        <th scope="col">작성시간</th>
    </tr>
    </thead>
    {{#searchList}}
        <tbody>
        <tr>
            <th scope="row">{{id}}</th>
            <td><a href="/{{id}}">{{title}}</a></td>
            <td>{{author}}</td>
            <td>{{createdTime}}</td>
        </tr>
        </tbody>
    {{/searchList}}
</table>

{{>search/searchForm}}

{{>layout/footer}}

 

템플릿은 Mustache를 사용 중이고 위에 코드는 검색 리스트를 뿌려주는 파일이다

 

1-5 searchForm.mustache

<form action="/board/search" method="GET">
    <div class="btn-group" role="group" aria-label="Basic example">
        <input name="keyword" type="text" placeholder="검색어를 입력해주세요">
        <button class="btn btn-secondary">검색</button>
    </div>
</form>

 

다음은 검색창이다

폼 데이터를 해당 주소로 GET 하는 걸 볼 수 있다

input에 데이터를 입력하게 되면 Controller가 해당 데이터를 받아 지지고 볶은 다음에 searchPage에 보낸다

그럼 searchPage가 데이터를 받아 화면을 구성한다

 

1-6 결과

 

7을 검색했을 때 제목에 7이 포함된 글들을 가져오는 걸 확인할 수 있다. 참고로 테스트 제목 1~30까지 있음

 

 

URL 확인

 

 

 

2. 페이징 처리

 

1-1 Service

@Transactional
    public Page<Board> getBoardList(Pageable pageable) {

        return boardRepository.findAll(pageable);

    }

 

서비스에서 구현한 페이징 기능이다

어떻게 해야 할지 구글링을 해봤는데 많이 복잡하더라

그래서 좀 더 쉽게 하는 방법이 없나 찾아보다가 Pageable을 발견했다. 이를 이용하면 정말 쉽게 페이징 처리를 할 수 있다

신기했다. 페이징 처리하기 위해서 이거 쓰고  저거 쓰고 되게 복잡해 보였는데,

Pageable은 JpaRepositroy.findAlll() 파라미터로 pageable만 넣어주면 끝난다

정말 놀라웠다

주의할 점은 리스트 타입을 Page로 해야 함

 

1-2 Controller

@GetMapping("/")
    public String index(Model model, @PageableDefault(size = 10, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
    
        model.addAttribute("boardList", boardService.getBoardList(pageable));

        return "index";
    }

 

다음은 컨트롤러 부분이다. 본인은 메인화면에 리스트를 뿌리고 있기 때문에 index파일에 해당 기능을 구현해주었다

사용법은 정말 쉽다

@PageableDefault 어노테이션을 사용하면 끝난다.

정렬 기능 또한 이 어노테이션으로 해결 가능하다

@PageableDefault을 쓰기 전에는 레파지토리에 정렬 쿼리를 작성해주고 서비스에서 구현하고 사용했다

근데 @PageableDefault 어노테이션을 쓰면 정렬은 물론 페이징 처리, 페이지 사이즈까지 한 줄로 구현 가능

 

여기까지 코드를 작성했다면 페이징 처리는 끝났다

 

 

 

????????????

 

 

코드를 적은 거 같지도 않은데 기능 구현이 다 됐다

오홍홍

설레는 마음으로 결과물을 보자

 

1-3 결과물

 

페이지 사이즈가 10이고, id를 기준으로 내림차순 정렬된 걸 확인할 수 있다

그리고 주의할게 하나 있다

 

 

URL을 보면 page값이 있다

근데 page값이 1인데 왜 11~20 글이 나오냐? (참고로 1~30까지 있음)

가장 첫 페이지(내림차순이기 때문에 21~30), 즉 21~30의 page값은 0이다

쉽게 말해 0이 시작인 셈이다

 

 

 

3. 검색 페이지에서 페이징

 

1-1 Repository

public interface BoardRepository extends JpaRepository<Board, Long> {

    List<Board> findByTitleContaining(String keyword, Pageable pageable);

}

 

다음은 검색한 결과에 대한 페이징 처리이다

코드를 보면 알겠지만 위에서 다룬 검색 메서드에서 파라미터로 Pageable만 추가했다

 

1-2 Service

@Transactional
    public List<Board> search(String keyword, Pageable pageable) {

        List<Board> boardList = boardRepository.findByTitleContaining(keyword, pageable);

        return boardList;
    }

 

아까 작성한 서비스 파일 내에 검색 메서드에 Pageable을 추가해주면 끝

근데 코드를 보면 위에서 작성한 코드랑 차이점이 있다

 

    // 검색기능
    @Transactional
    public List<Board> search(String keyword, Pageable pageable) {

        List<Board> boardList = boardRepository.findByTitleContaining(keyword, pageable);

        return boardList;
    }
    
    // 페이징처리
    @Transactional
    public Page<Board> getBoardList(Pageable pageable) {

        return boardRepository.findAll(pageable);

    }

 

위에 두 코드를 비교해보면 리스트 타입이 다른 걸 확인할 수 있다

위에는 List로 받고, 아래는 Page로 받는다

다른 이유는 JpaRepository가 제공하는 기본 메서드인 findAll()에 Pageable을 사용할 경우에는 리스트 타입을 Page로 해줘야 한다

 

1-3 Controller

  @GetMapping("/board/search")
    public String search(String keyword, @PageableDefault(size = 10, sort = "id", direction = Sort.Direction.DESC) Pageable pageable ,Model model) {

        List<Board> searchList = boardService.search(keyword, pageable);

        model.addAttribute("searchList", searchList);

        return "search/searchPage";
    }

 

마지막으로 컨트롤 부분이다

마찬가지로 아까 작성한 검색 메서드에 파라미터로 Pageable만 추가해주면 된다

 

1-4 결과물

 

1로 검색했을 시 페이지 사이즈가 10으로, 내림차순으로 정렬된 걸 확인할 수 있다

그럼 나머지 검색 결과는?

 

 

URL에 page=1로 이동하니 나머지 검색 결과들이 다음 페이지에 나오는 걸 확인할 수 있다

 

 


 

이렇게 검색 및 페이징 처리 포스팅은 끝이다

아직 구현 못한 기능이 있는데, pagination이다

현재 mustache를 쓰는데 저 URL에 page=숫자 부분을 동적으로 바꾸고 싶은데 어떻게 해야 할지 모르겠다

구글링을 해도 모르겠어  ㅜㅜㅜㅜ

아마 다음 숙제는 이거이지 않을까 싶네