JpaRepository 를 상속해서 사용할 수 있는 메소드 중
findAll() 메소드는
Page<T> findAll(Pageable pageable);
위와 같이 Page 처리에 대한 정보를 담고있는 Pageable 객체를 매개변수로 받아서,
목표로 하는 T 객체를 페이징처리하여 Page 객체타입으로 받아내는 기능을 제공합니다.
Pageable 는
Pageable pageable = PageRequest.of(
pageRequestDTO.getPage() - 1, pageRequestDTO.getSizePerPage(),
Sort.Direction.DESC, "createdDate"
);
PageRequest (자식) 객체를 이용해서,
PageRequest.of( 1.현재페이지, 2.페이지당 데이터개수, 3.정렬 순서, 4."정렬기준필드" );
정보를 토대로, 어떻게 페이징 처리를 할것인 지 에 대한 정보를 pageable 객체에 담아둡니다.
final Page<PostEntity> pageData = postRepository.findAll(pageable);
List<PostEntity> allPosts = pageData.getContent();
페이징에 대한 정보를 담고있는 pageable 객체를 이용해서, findAll( ) 메소드를 쓰면
Page<목표DTO> 객체에
현재 페이지, 페이지당 데이터개수, 정렬기준으로 정렬된 데이터를 Page 객체에 담아둡니다.
.getContent() 메소드를 사용해 해당하는 데이터들을 뽑아 쓸 수 있고,
pageData. getTotalElements() : 총 데이터 개수
pageData.getTotalPages() : 총 페이지 수
부가적인 페이징에 관한 정보들 또한 사용할 수 있습니다.
위에서, Pageable 객체를 만들 때 필요한 페이징에 대한 정보
1. 현재 페이지
2. 페이지당 데이터 개수
위의 정보들이 있어야 Pageable 객체를 만들고, Page 객체를 만들어 사용할 수 있으므로
위의 정보들을 받아올 수 있는 Page정보용 DTO를 만들어 사용합니다.
@ToString @Getter @Setter
public class PageRequestDTO {
private int page; // 요청한 페이지 번호
private int sizePerPage; // 한페이지 당 데이터 개수
// 기본생성자 => 초기 세팅 => int 기본 값 0 으로 잡혀있으니까 기본 값 1로 설정, sizeperPage 설정
public PageRequestDTO() {
this.page = 1;
this.sizePerPage = 3;
}
// Setter 이용 트롤 처리
public void setPage(int page) {
// 예외처리 => 공격자들이 페이지 번호를 음수를 줘버리거나, 이상한 값을 줄 경우, page 1 로 설정. 그리고 날려보냄
if (page < 0 || page > Integer.MAX_VALUE) {
this.page = 1;
return;
}
this.page = page; // 기본 세터
}
public void setSizePerPage(int sizePerPage) {
if (sizePerPage < 10 || sizePerPage > 100) {
this.sizePerPage = 10; // 이거 공격자가 선넘게 이상하게 고쳐두면 10 으로 설정.
return;
}
this.sizePerPage = sizePerPage;
}
}
클라이언트에서 page 에 대한 정보를 이 페이지정보DTO로 받아서
=> Pageable 객체를 생성, 이 객체를 이용해서
=> Page<목표Entity> 객체를 생성
=> .getContent( ) 등 메소드를 이용해 페이지 처리 된 데이터를 사용
@RequestMapping(value = "", method = RequestMethod.GET)
public ResponseEntity<?> getAllPosts(PageRequestDTO pageRequestDTO) {
PostListResponseDTO allList = postService.getAllList(pageRequestDTO);
- 이렇게 하면,
총 페이지 수,
총 데이터 수,
현재 페이지,
페이지 당 데이터 수,
해당하는 데이터
를 가지고 있습니다.
서버단에서는 이 정보들을 이용해
페이징에서 현재 페이지 기준, prev / next 처리를 할 수 있도록
1. 페이징 startPage
2. 페이징 endPage
3. 실제 endPage
4. prev 활성화 boolean
5. next 활성화 boolean
등의 정보를 처리해 클라이언트 단으로 보내줍니다.
@ToString @Setter @Getter
@Builder @NoArgsConstructor @AllArgsConstructor
public class PageResponseDTO<T> {
// Paging 처리 할 수 있는 정보들 ( startPage, endPage, currentPage, prev, next, totalCount ) 넘겨줘야 함
// current 페이지 기준으로
// start end 는 페이징 번호 몇번 부터 몇번까지 보여줄 지
// prev next 는 이전 다음 활성화
private int startPage;
private int endPage;
private int currentPage;
private boolean prev;
private boolean next;
private int totalCount;
// prev / next 당 보여 줄 페이지 수
private static final int PAGE_COUNT = 3;
// 생성자 설정
public PageResponseDTO(Page<T> pageData) {
// index 니까 +1 해줘야 클라에서 보이는 진짜 currentPage 숫자
this.currentPage = pageData.getPageable().getPageNumber() + 1; //Pageable 쓰면 PageNumber 가져올 수 있음
// current가 34 번째 페이지 라면, 페이지 개수 10 개로 잡았을 때, 3.4 ceil => 4 => 40 페이지로 endPage를 만들겠다.
// 나눌 때, int / int 로 나누면 int 로만 나오니까, double 변환 해줘야 3.4 로 나오겠지
this.endPage = (int)Math.ceil((double)currentPage / PAGE_COUNT) * PAGE_COUNT;
// 근데 이거 찐 마지막 페이징에서는 적용 안됨 => 보정설정
this.startPage = endPage - PAGE_COUNT + 1;
this.totalCount = (int)pageData.getTotalElements(); //long 타입이라 int 로 다운그레이드
// int realEnd = (int) Math.ceil((double) totalCount / pageData.getSize());
// JPA 로는
int realEnd = pageData.getTotalPages(); // 실제 end 페이지 구해줌
this.prev = startPage > 1; // startPage 가 1 보다 크면 true 다. 1이면 false 처리
if (realEnd < endPage) {
this.endPage = realEnd;
}
// 마지막 구간에서만 보정해주는 설정 - endPage 를 realEnd 페이지로 설정
this.next = endPage < realEnd;
}
}
클라이언트 단으로 보낼 때는
1. 페이징 처리 된 DTO 데이터 자료 (List)
2. start,endPage 등 정보를 보낼 pageResponseDTO
등을 같이 보내야 하므로,
이들을 포장해서 보내줄 큰 DTO 객체를 만들어, 여기에 담아서 클라이언트 단에 보내줍니다.
public class PostListResponseDTO {
private int count;
// 페이지정보 객체
private PageResponseDTO pageInfo;
// 데이터 List
private List<PostResponseDTO> posts;
}
PostListResponseDTO listResponseDTO = PostListResponseDTO.builder()
.count(responseDTOList.size())
.pageInfo(new PageResponseDTO<PostEntity>(pageData))
.posts(responseDTOList)
.build();
return listResponseDTO;
클라이언트단에서는 start, endPage, realEndPage, 페이징 된 dtoList 데이터 등을 받아
페이징 처리를 해주게 됩니다.
JpaRepository를 상속했을 때 사용할 수 있는
Page<T> findAll(Pageable pageable)
메소드를 이용해 페이징 처리에 도움을 받을 수 있지만, 그래도 페이징은 역시나 복잡한 영역인 듯 합니다.
eGov 프레임워크에서도 Paging 처리를 위해 제공되는 기능들이 있어서 활용할 수 있는데
다음에는 eGov 환경에서 페이징처리 구현을 시도해 봐야겠습니다.
https://alisyabob.tistory.com/243
전자정부프레임워크 Pagination 페이징처리
전자정부프레임워크 Pagination 페이징처리 기본적으로 전자정부 프레임워크에서는 페이징 처리를 편하게 하기 위해 태그를 제공한다. PaginationInfo는 렌더링에 필요한 데이터가 담겨져있는 빈 클
alisyabob.tistory.com
'Back to the Spring' 카테고리의 다른 글
사용자의 요청DTO => @Validated 검사 (0) | 2023.01.18 |
---|---|
[ Spring ] RestAPI 만능 객체 ResponseEntity<?> (0) | 2023.01.15 |
[ Spring ] 프레임워크, DI, Entity / DTO (0) | 2023.01.15 |
[Spring Security] Authentication Failure Handler 적용 (0) | 2022.12.24 |
[ Spring Security ] OAuth2 구글 / 네이버 로그인 (2) | 2022.12.23 |