페이징 1. - 계층별 페이지 구현

알파로그·2023년 3월 21일
0

Spring Boot

목록 보기
19/57
post-custom-banner

✏️ 계층별 페이징 구현 방법

📍 Repostiory interface 계층

  • 단순히 모든 data 를 조회하는 find all 이 아닌,
    페이징 data 를 추가로 받는 find all 을 생성한다.
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface QuestionRepository extends JpaRepository<Question, Integer> {

    //-- 페이징을 위한 로직 --//
    Page<Question> findAll(Pageable pageable);

📍 Service 계층

  • getList 의 매개변수에 조회를 원하는 페이지 번호를 받는다.
  • Sort.Order.desc()
    • column 을 기준으로 정렬을 해주는 라이브러리이다.
    • Param 값으로 entity 의 필드값인 createDate 를 입력해 생성 날짜 기준으로 정령하도록 했다.
    • 만약 추가로 정렬해야될 column 이 있다면 sorts 에 추가로 add 해주면 된다.
  • PageRequest.of
    • 첫번째 Param : 조회할 페이지의 번호
    • 두번째 Param : 한 페이지에 보여줄 row 의 숫자
    • 세번째 Param : row 의 정렬 순서를 결정하는 부분이다.
      • 세번째 Param 을 생략되면 빨리 생성된 row 부터 보여진다.
  • data 를 페이징해서 Controller 에 전달하게 된다.
@Service
@RequiredArgsConstructor
public class QuestionService {

    private final QuestionRepository questionRepository;

    //-- paging X --//
    public List<Question> getList() {
        return this.questionRepository.findAll();
    }

    //-- paging --//
    public Page<Question> getList(int page) {
        List<Sort.Order> sorts = new ArrayList<>();
        sorts.add(Sort.Order.desc("createDate"));

        Pageable pageable = PageRequest.of(page, 10, Sort.by(sorts));
        return this.questionRepository.findAll(pageable);
    }

📍 Controller 계층

  • 요청할 때 페이지를 파라미터를 추가로 받는다.
    • 만약 페이지를 받지 안을경우 기본값으로 “0” 을 받아 첫번째 페이지를 응답한다.
    • spring boot 의 첫번째 페이지는 1 이 아닌 0 이다.
  • Service 에서 만든 페이징 findAll 을 선언해 paging 된 data 를 model 에 넘겨준다.
@Controller
@RequestMapping("/question")
@RequiredArgsConstructor
public class QuestionController {

    private final QuestionService questionService;

    //-- Get 방식으로 페이징 적용 --//
    @GetMapping("/list")
    public String list(
            @RequestParam(defaultValue = "0") int page,
            Model model
    ) {
        Page<Question> paging = this.questionService.getList(page);

        model.addAttribute("paging", paging);
        return "question_list";
    }

⚠️ paging 의 추가기능

항목설명
paging.isEmpty페이지 존재 여부 (게시물이 있으면 false, 없으면 true)
paging.totalElements전체 게시물 개수
paging.totalPages전체 페이지 개수
paging.size페이지당 보여줄 게시물 개수
paging.number현재 페이지 번호
paging.hasPrevious이전 페이지 존재 여부
paging.hasNext다음 페이지 존재 여부

✏️ 페이지 이동기능 구현

지금까지 만들고 서버를 실행시켜보면 정상적으로 페이징 된것을 확인할 수 있다.

그리고 url 에 직접 page 파라미터를 입력하면 다른 페이지로 이동되는 것도 확인할 수 있다.


이제 web 계층에서 url 이 아닌 ui 를 통해서 더욱 편하게 페이지를 이동하는 기능을 구현해야 한다.

📍 Web 계층

  • Controller 에서 Model 을 통해 받은 “paging” 을 기반으로 작업된다.
  • 핵심 로직은 세개의 li 에서 작동된다.
    • 첫번째 li 는 이전 버튼에 대한 로직
    • 두번째 li 는 페이지 번호에 대한 로직
      • each 를 통해서 마지막 페이지 까지 번호가 생성된다.
    • 세번째 li 는 다음 버튼에 대한 로직
  • th:classappend="${!paging.hasPrevious()} ? 'disabled'"
    • 이전 또는 다음 페이지가 없을경우 버튼이 비활성화 되게 만드는 로직이다.
    • th:classappend="조건식 ? 클래스값”
    • 조건식이 참인 경우 클래스값을 class 속성에 추가한다.
  • th:classappend="${page == paging.number} ? 'active'"
    • each 문의 반복 도중 “pagin” 의 번호와 같다면 active 를 통해 글씨체를 두껍게 만들어 주는 로직이다.
<!--    페이징 처리 시작 -->
    <div th:if="${!paging.isEmpty()}">
        <ul class="pagination justify-content-center">
            <li class="page-item" th:classappend="${!paging.hasPrevious()} ? 'disabled'">
                <a class="page-link"
                   th:href="@{|?page=${paging.number-1}|}">
                    <span>이전</span>
                </a>
            </li>
            <li th:each="page: ${#numbers.sequence(0, paging.totalPages-1)}"
                th:if="${page >= paging.number-5 and page <= paging.number+5}"
                th:classappend="${page == paging.number} ? 'active'"
                class="page-item">
                <a th:text="${page}" class="page-link" th:href="@{|?page=${page}|}"></a>
            </li>
            <li class="page-item" th:classappend="${!paging.hasNext} ? 'disabled'">
                <a class="page-link" th:href="@{|?page=${paging.number+1}|}">
                    <span>다음</span>
                </a>
            </li>
        </ul>
    </div>
<!--    페이징 처리 종료-->

⚠️ 페이징 기능 정리

페이징 기능코드
이전 페이지가 없으면 비활성화th:classappend="${!paging.hasPrevious} ? 'disabled'"
다음 페이지가 없으면 비활성화th:classappend="${!paging.hasNext} ? 'disabled'"
이전 페이지 링크th:href="@{
다음 페이지 링크th:href="@{
페이지 리스트 루프th:each="page: ${#numbers.sequence(0, paging.totalPages-1)}"
현재 페이지와 같으면 active 적용th:classappend="${page == paging.number} ? 'active'"
  • #numbers.sequence(시작, 끝)
    • 은 시작 번호부터 끝 번호까지의 루프를 만들어 내는 타임리프의 유틸리티이다.
profile
잘못된 내용 PR 환영
post-custom-banner

0개의 댓글