게시판 페이징을 구현하여 게시글 리스트를 불러오려고 한다. 아래의 사진과 같이 구현하고자 하였다.
- 게시물 5개씩 불러오기
- Pagination 부분에 7개 고정하기
먼저 Board Entity에서 리스트로 끌어올때 필요한 정보들을 모아둔 DTO를 구성했다.
@Getter
public class BoardListDTO {
private long bno;
private String title;
private int readCount;
private String writer;
private LocalDateTime updatedDate;
private LocalDate toDay;
private String writerId;
//Entity를 -> BoardListDTO(BoardEntity ent)
public BoardListDTO(BoardEntity ent) {
this.bno = ent.getBno();
this.title = ent.getTitle();
this.readCount = ent.getReadCount();
this.writer = ent.getMember().getName(); //member의 name이 작성자임
this.updatedDate = ent.getUpdatedDate();
toDay=LocalDate.now();
this.writerId =ent.getMember().getId();
}
}
다음으로 DB에 저장된 게시물 리스트를 불러오는 getListAll 메서드를 ServiceProcess에 작성을 해주었다.
우선 JPA에서 기본적으로 pageable을 제공한다. 페이징에 이를 이용했다.
- Page<T> : 페이지 정보를 담는 인터페이스
- Pageable : 페이지 처리에 필요한 정보를 담는 인터페이스
getListAll이라는 메소드에 변수로 page와 model를 이용해 데이터를 담아 오려고 한다.
@Transactional
@Override
public void getListAll(int page, Model model) {
//board list를 페이지로 전송
//페이징 작업 pageable이용
int size=5; // 5개씩 보이게
Sort sort=Sort.by(Direction.DESC, "bno");
Pageable pageable=PageRequest.of(page-1, size ,sort);
Page<BoardEntity> result=repository.findAll(pageable);
int nowPage = result.getNumber()+1;
int startPage = Math.max(nowPage -3, 1);
int endPage = Math.min(nowPage +3, result.getTotalPages());
int totPage= result.getTotalPages();
model.addAttribute("nowPage", nowPage);
model.addAttribute("startPage", startPage);
model.addAttribute("endPage", endPage);
model.addAttribute("totPage", totPage);
model.addAttribute("p", result);
model.addAttribute("list", result.stream()
.map(BoardListDTO::new)
.collect(Collectors.toList()));
}
- page 는 게시글의 인덱스 번호이다.
- size 는 한 페이지에 몇개의 게시물을 보여줄지 결정한다. 나는 size를 5로 설정하였다.
- sort 는 정렬 방법이다. 나는 bno라는 게시물 번호를 이용하여 DESC 즉, 내림차순으로 정렬하고자 하였다.
그리고 Page에서 아래와 같은 메소드를 제공한다. 이를 이용하여 nowPage, startPage, endPage를 직접 설정해주었다.
getNumber() | 현재 페이지 인덱스를 불러온다. 0부터 시작이다. |
getTotalPages() | 전체 페이지의 개수를 불러온다. |
hasPrevious() | 이전 페이지가 존재하는지 확인한다. |
hasNext() | 다음 페이지가 존재하는지 확인한다. |
이제 controller에서 작성한 메소드를 이용해 매핑해보자.
@GetMapping("/notice-boards")
public String board(@RequestParam(defaultValue = "1") int page , Model model) {
service.getListAll(page ,model);
return "board/noticeList";
}
다음으로 보이는 뷰에 페이징을 구현을 해보자. thymeleaf 문법사용에 주의하며 작성하였다. if 문이 꽤나 복잡하게 사용되었는데 page개수가 보이는 것을 7개로 고정하기 위해 짠 로직들이다.
- 단순히 th:each="p:${#numbers.sequence(startPage, endPage)}" 를 이용 할 수 없다.
전, 후로 3페이지씩 가지고 있는 페이지들은 정상적으로 페이지 개수가 7개로 고정이 된다.
하지만 예를들어 1페이지 같은 경우는 이전 페이지들이 없다. 따라서 int startPage = Math.max(nowPage -3, 1) 에 따라 시작 페이지가 1페이지가 되고, endPage는 4페이지가 된다. 그러면 7개의 페이지 개수가 고정이 되지 않는다.
이러한 여러 문제들을 다양한 조건문들을 작성하여 예외가 발생하는 문제들을 해결 할 수 있었다.
<div class="page_wrap">
<div class="page_nation">
<div th:if="${p.getNumberOfElements()>0}">
<a class="arrow prev" th:if="${p.hasPrevious()}" th:href="|/notice-boards?page=${nowPage-1}|"><</a>
<th:block th:if="${totPage>=6}">
<th:block th:if="${nowPage <= 4}" th:each="p:${#numbers.sequence(1, 7)}">
<a th:if="${p != nowPage}" th:href="@{notice-boards?(page=${p})}" th:text="${p}"></a>
<a th:if="${p == nowPage}" th:text="${p}" class="active"></a>
</th:block>
<th:block th:if="${nowPage>4 && nowPage<totPage-2}" th:each="p:${#numbers.sequence(startPage, endPage)}">
<a th:if="${p != nowPage}" th:href="@{notice-boards?(page=${p})}" th:text="${p}"></a>
<a th:if="${p == nowPage}" th:text="${p}" class="active"></a>
</th:block>
<th:block th:if="${nowPage >= totPage-2}" th:each="p:${#numbers.sequence(nowPage-(6-(totPage-nowPage)), totPage)}">
<a th:if="${p != nowPage}" th:href="@{notice-boards?(page=${p})}" th:text="${p}"></a>
<a th:if="${p == nowPage}" th:text="${p}" class="active"></a>
</th:block>
</th:block>
<th:block th:if="${totPage<6}">
<th:block th:each="p:${#numbers.sequence(startPage, endPage)}">
<a th:if="${p != nowPage}" th:href="@{notice-boards?(page=${p})}" th:text="${p}"></a>
<a th:if="${p == nowPage}" th:text="${p}" class="active"></a>
</th:block>
</th:block>
<a class="arrow next" th:if="${p.hasNext()}" th:href="|/notice-boards?page=${nowPage+1}|">></a>
</div>
</div>
</div>
'SpringBoot Project' 카테고리의 다른 글
[SpringBoot] 게시물 수정, 삭제 작성자일 때만 가능하게 하기(thymeleaf 이용) (0) | 2023.01.29 |
---|---|
[SpringBoot] 게시판 게시물 조회수 기능 (0) | 2023.01.28 |
[SpringBoot] 게시판 게시물 삭제하기(delete) (0) | 2023.01.23 |