페이지네이션이란?
데이터의 양이 많아 한번에 보여주기 어려운 경우, 페이지를 번호로 구분해 데이터를 나눠 보여줍니다.
페이지네이션 vs 무한 스크롤
페이지네이션 | 무한스크롤 | |
장점 | 위치를 파악하기 쉽다. (전자상거래 사이트에 어울리는 방식) |
사용자가 오래 머무르게 됨 (SNS에 어울리는 방식) |
단점 | 사용자 경험이 떨어짐 | 페이지 성능이 떨어짐 |
페이지네이션 구현
public class PostReadService {
public Page<Post> getPosts(Long memberId, PageRequest pageRequest) {
}
}
스프링에서 제공하는 Page와 PageRequest를 사용하여 구현하려고 합니다.
Page는 <>안의 클래스를 받아서 페이지를 구현합니다.
PageRequest는 페이지 번호, 페이지 크기, 정렬 방식을 지정하는데 도움을 줍니다.
public class PostRepository {
private static final RowMapper<Post> POST_ROW_MAPPER = (rs, rowNum) -> Post.builder()
.id(rs.getLong("id"))
.memberId(rs.getLong("memberId"))
.content(rs.getString("contents"))
.createdDate(rs.getDate("createdDate").toLocalDate())
.createdAt(rs.getDate("createdAt").toLocalDate())
.build();
public Page<Post> findAllByMemberId(Long memberId, Pageable pageable) {
/*
memberId로 게시글을 조회하는 쿼리를 작성해주세요.
*/
var sql = """
SELECT *
FROM post
WHERE memberId = :memberId
LIMIT :size OFFSET :offset;
""";
var params = new MapSqlParameterSource()
.addValue("memberId", memberId)
.addValue("size", pageable.getPageSize())
.addValue("offset", pageable.getOffset());
var posts = jdbcTemplate.query(sql, params, POST_ROW_MAPPER);
return new PageImpl(posts, pageable, getCount(memberId));
}
private Long getCount(Long memberId) {
var sql = """
SELECT count(*)
FROM post
WHERE memberId = :memberId;
""";
var params = new MapSqlParameterSource()
.addValue("memberId", memberId);
return jdbcTemplate.queryForObject(sql, params, Long.class);
}
POST_ROW_MAPPER를 통해 post 객체를 생성합니다.
findAllByMemberId메서드는 memberId로 특정 회원의 게시글을 조회하는 기능을 하고 있습니다.
SQL 쿼리를 사용하여 데이터베이스에서 게시글을 가져오는데 Pageable객체를 이용하여 파라미터 값을 넣어줍니다.
jdbcTemplate.query를 통해 SQL 쿼리를 실행하고, POST_ROW_MAPPER를 사용하여 각 행을 Post객체로 매핑합니다.
PageImpl을 사용하여 Page<Post>를 생성하고 반환합니다.
:size
페이지당 항목 수
:offset
몇 번째 페이지인지에 대한 정보
public PageImpl(List<T> content, Pageable pageable, long total)
PageImpl객체를 생성할 때,
content에는 jdbcTemplate.query를 통해 가져온 Post객체의 목록이,
pageable에는 사용자가 요청한 페이지 및 정렬 정보가,
total에는 전체 게시글 수가 전달됩니다.
@GetMapping("/members/{memberId}")
public Page<Post> getPost(
@PathVariable Long memberId,
@RequestParam Integer page,
@RequestParam Integer size) {
return postReadService.getPosts(memberId, PageRequest.of(page, size));
}
구현된 엔드포인트를 통해 클라이언트는 특정 회원의 게시글을 페이지네이션하여 조회할 수 있습니다.
정렬추가
public class PageHelper {
public static String orderBy(Sort sort) {
if (sort.isEmpty()) {
return "id Desc";
}
List<Sort.Order> orders = sort.toList();
var orderBys = orders.stream()
.map(order -> order.getProperty() + " " + order.getDirection())
.toList();
return String.join(", ", orderBys);
}
PageHelper라는 클래스를 통해 앞서 구현된 리포지토리의 sql 쿼리문에 삽입될 ORDER BY 에 대한 내용을 정의합니다.
우선 sort역시 Spring Data에서 제공하는 것으로 SQL 쿼리의 ORDER BY 절을 생성하는 유틸리티 메서드입니다.
만일 sort가 비어있을 경우 기본적으로 id필드를 기준으로 내림차순 정렬합니다.
그렇지 않은 경우에는 String.join(", ", orderBys)를 사용하여 모든 정렬 순서를 쉼표로 구분된 문자열로 결합합니다.
'DB(MySQL, MongoDB, Redis, Kafka) > MySQL' 카테고리의 다른 글
MySQL 조회 최적화를 위한 인덱스 테스트 [EazyRandom] (0) | 2023.12.29 |
---|---|
MySQL 테스트를 위한 SNS서비스 팔로우 (2) | 2023.12.27 |
MySQL 테스트를 위한 SNS서비스 회원이름 변경 및 변경내역 조회 (0) | 2023.12.27 |
MySQL 테스트를 위한 SNS서비스 회원정보 조회 (0) | 2023.12.26 |
MySQL 테스트를 위한 SNS서비스 회원정보 등록 (0) | 2023.12.26 |