Slice 무한스크롤로 구현하는 상황에 데이터가 중복되는 상황이 일어났다... 문제의 api는 인기순인 투표를 조회하는 쿼리이다
ERD의 일부이다
vote에 투표를 하면 vote_result가 생기는데 인기순으로 조회하려면 vote에 해당되는 vote_result가 많으면 많을수록 인기순이 높아진다
이 코드 이다 현재 Slice를 구현하기 위해 limit + 1해서 List로 반환하고(hasNext를 알기 위해)
@Component
public class PageableConverter {
private static final int INDEX_OF_START_SUBLIST = 0;
public <T> SliceImpl<T> convertListToSlice(List<T> list, int pageNum, int pageSize) {
if (list.isEmpty()) {
return new SliceImpl<>(list);
}
if (list.size() < pageSize) {
pageSize = list.size();
}
Pageable pageable = PageRequest.of(pageNum, pageSize);
int start = INDEX_OF_START_SUBLIST;
int end = Math.min((start + pageable.getPageSize()), list.size());
List<T> subList = new ArrayList<>(list.subList(start, end));
boolean hasNext = end < list.size();
return new SliceImpl<>(subList, pageable, hasNext);
}
}
이렇게 Slice객체로 바꿔준다
page = 0, size = 3넣으면
"voteSlice": {
"content": [
{
"voteId": 19,
"postedUserId": 1,
"title": "경북의 자존심, 골라주세요!",
"detail": "솔직히 경북 술은 고도리 복숭아 와인이 진리인데\n친구녀석이 자꾸 문경바람 백자가 진리라고 하니까 너무 분함 ㅡㅡ\n\n복숭아 맛있는데...문경 술 좋아한다네요\n\n\n아 그래도 복숭아와인이 짱인데!\n술맛도 모르는 녀석이 까부네\n\n님덜 얼른 어떤 술이 진리인지 골라주셈\n골라주면 복받을거임 ❤️ ",
.....
},
{
"voteId": 34,
"postedUserId": 16,
"title": "오늘 행궁동 가는데 어떤거 마실까요?",
"detail": "행궁동 전통주 바 가는데 요거 두개가 제 맘에 들어요~~~ 하나 결정해주시면 그걸로 오늘 마실게요 ^ㅠ^",
.....
},
{
"voteId": 28,
"postedUserId": 3,
"title": "삼양춘 술 먹어보신분 있나요?",
"detail": "이번에 인천으로 여행을 가게 되었는데 삼양춘 술들이 유명하더라고요 \n그래서 하나 마셔보려고 합니다.\n생약주랑 탁주 드셔보신분 계신가요? 알려주세요!",
.....
}
이렇게 나오고 여기서 page = 1, size = 3넣으면
{
"voteId": 28,
"postedUserId": 3,
"title": "삼양춘 술 먹어보신분 있나요?",
"detail": "이번에 인천으로 여행을 가게 되었는데 삼양춘 술들이 유명하더라고요 \n그래서 하나 마셔보려고 합니다.\n생약주랑 탁주 드셔보신분 계신가요? 알려주세요!",
.....
이렇게 나온다 28번이 한번 더 나온다
여기서 그냥 page = 0 size = 4넣으면
"voteSlice": {
"content": [
{
"voteId": 19,
"postedUserId": 1,
"title": "경북의 자존심, 골라주세요!",
"detail": "솔직히 경북 술은 고도리 복숭아 와인이 진리인데\n친구녀석이 자꾸 문경바람 백자가 진리라고 하니까 너무 분함 ㅡㅡ\n\n복숭아 맛있는데...문경 술 좋아한다네요\n\n\n아 그래도 복숭아와인이 짱인데!\n술맛도 모르는 녀석이 까부네\n\n님덜 얼른 어떤 술이 진리인지 골라주셈\n골라주면 복받을거임 ❤️ ",
.....
},
{
"voteId": 34,
"postedUserId": 16,
"title": "오늘 행궁동 가는데 어떤거 마실까요?",
"detail": "행궁동 전통주 바 가는데 요거 두개가 제 맘에 들어요~~~ 하나 결정해주시면 그걸로 오늘 마실게요 ^ㅠ^",
.....
},
{
"voteId": 32,
"postedUserId": 41,
"title": "부산 여행을 갑니다!!",
"detail": "친구들과 여행가게되서 소주,맥주 보단 부산 막걸리를 한번 먹어보려는데 막걸리 어떤게 부산항을 진하게 느낄 수 있을까요?.
.....
},
{
"voteId": 28,
"postedUserId": 3,
"title": "삼양춘 술 먹어보신분 있나요?",
"detail": "이번에 인천으로 여행을 가게 되었는데 삼양춘 술들이 유명하더라고요 \n그래서 하나 마셔보려고 합니다.\n생약주랑 탁주 드셔보신분 계신가요? 알려주세요!",
.....
page = 0 size = 3을 했을때 쿼리 내부에서 limit + 1해서 voteId 19 34 32 28 까지 나오는데 여기서
page = 1 size = 3을 하면 limit + 1해서 voteId 32 39 33 28이 나온다 28이 짤려야되는데 32가 짤리고 28이 두번나온다 결론은 28은 중복되고 32가 짤리는 것이였다 이유가 예상이 된다 vote result 의 개수가 32 와 28이 5로 같아서 였다
쿼리를 직접 limit + 1해서 실행해보니 예상이 맞았다
해결방법은 orderBy(vote.id.count desc, created date desc) 이걸로 인기순이 동률이면 최신순으로 조회하면 해결이 된다