가장 중요한 것 Pagination이란 무엇인가 우리가 구현하기에 앞서 먼저 알고가야 하는 용어입니다
꼭 보세요!! 아니면 나중에 헷갈려요
만약 DB에 수만 수억가지 데이터들이 있는데 그 데이터들을 한 번에 불러와서 본다면 당연히 좋겠죠? 하지만 그렇다면 부하가 생길수 밖에 없습니다 무수히 많은 쿼리들 때문이죠
그래서 우리는 많은 어플에서 보듯이 무한스크롤등을 구현하는 곳이 많습니다
예를들어 오른쪽에 인스타그램 처럼요!
그렇다면 각각의 내용들을 어떻게 효율적으로 불러올까요?
먼저 많은 방식들이 있지만 저는 오늘 Slice이용한 무한스크롤을 다룰예정입니다
1. No offset 사용하기
No offset이란 말 그대로 페이지 번호가 없는 방식을 이야기합니다
기존에는 페이지번호(offset)와 페이지 사이즈(limit)을 기반으로 하는 것과 다르게 말이죠
그럼 왜 No offset이 빠를까요?
쿼리문을 먼저 보자면
SELECT *
FROM items
WHERE 조건문
ORDER BY id DESC
OFFSET 페이지번호
LIMIT 페이지사이즈
제가 하는 프로젝트에서는 최근 글을 보는 목적이므로
DESC 내림차순으로 최근 -> 옛날 이라고 생각하시면 편하겠습니다
위와 같이 쿼리문을 날린다면 어떻게 될까?
---> 뒤로 갈수록 느려진다
이유는 offset 10,000, limit 100이라고 하면 10,100개의 행을 읽어야합니다
시작점 offset(10,000)부터 limit(100)까지 읽어야 하니까요
그럼 이중 내가 필요한 정보는 10,000~10,100인데
10,000개의 정보들은 버리는 거죠 즉 필요가 없는 쿼리문이 날라갑니다
No offset은 여기서 offset이 없으므로(시작점이 없다) 내가 원하는 페이지를 읽을수 있다는 거죠!!
자 이제 코드를 보면 (QueryDsl 환경설정을 필수로 해야합니다)
public class PostRepositoryImpl {
@Autowired
MemberRepository memberRepository;
private final EntityManager em;
private final JPAQueryFactory query;
public PostRepositoryImpl(EntityManager em, JPAQueryFactory query) {
this.em = em;
this.query = query;
}
public Slice<PostDto> searchBySlice(Long PostId, Long member_id, Pageable pageable)
{
Member member = memberRepository.findById(member_id).orElseGet(Member::new);
List<PostDto> results = query
.select(Projections.fields(PostDto.class,
post.post_id.as("post_id"),post.comment.as("comment"),
post.content.as("content"),post.emoticon.as("emoticon"),
post.likes.as("likes"), post.post_picture.as("post_picture"),
post.title.as("title"), post.member.as("member_id")))
.from(post)
.where(
// no-offset --> 요청한 lastPostId부터 Index가 시작됩니다
lastPostId(PostId),
post.member.eq(member)
)
.orderBy(post.post_id.desc())
.limit(pageable.getPageSize()+1) limit에서 요청한 페이지 사이즈보다 +1을 해서 조회하는 것입니다
.fetch();
//페이지가 마지막인지 체크
return checkLastPage(pageable, results);
}
// no-offset 방식 처리하는 메서드
private BooleanExpression lastPostId(Long PostId) {
if (PostId==null || PostId==0) {
return null;
}
return post.post_id.lt(PostId);
}
// 무한 스크롤 방식 처리하는 메서드
private Slice<PostDto> checkLastPage(Pageable pageable, List<PostDto> results) {
boolean hasNext = false;
//만약 조회한 글이 화면에 보여줄 글보다 갯수가 많으면
if (results.size() > pageable.getPageSize()) { //result.size()는 조회한 글 갯수
//pageable 화면에 보여줄 글 갯수
hasNext = true; //다음 글이 있다고 체크
results.remove(pageable.getPageSize()); //result에 확인용으로 추가한 +1의 글을
//지워줍니다
}
return new SliceImpl<>(results, pageable, hasNext);
}
}
주석을 보시면 다 이해가 되실 거라 생각합니다!
https://devjem.tistory.com/74해당 블로그를 보고 참고하여 쓴 글입니다
'스프링' 카테고리의 다른 글
[Spring] Github OAuth 2.0 + Jwt를 통해 로그인하기 (3) | 2023.05.18 |
---|---|
[Spring] TDD vs BDD 무엇인지알고 비교하기 (0) | 2023.03.12 |
[Spring] Spring Security이용한 JWT 로그인 구현기 (1) | 2023.01.28 |
[Spring] JWT Refresh Token 어디에 저장해야 할까? 그리고 꼭 저장해야 할까? (0) | 2023.01.25 |
[Spring] 자바의 대표적인 빌드 관리 도구 Maven vs Gradle 차이 (0) | 2023.01.04 |