포트폴리오/Eighteen
[트러블슈팅] 랜덤 Pagination 너무 쉽게 봤다.
do_hyuk
2025. 1. 9. 23:44
처음 페이지로 회원을 나눌 때 회원을 전체 조회 후 Shuffle을 한 뒤에 해당 리스트를 페이징하는 방법을 생각했었다.
하지만 페이지네이션 특성 상 api를 호출할 때마다 다음 페이지를 요청해야하는데 이때 기준이 되는 회원 리스트는 DB에 저장되어 있는데 회원 테이블을 기준으로 하게 된다.
그렇기 때문에 기존에 생각했던 방식은 회원 전체 조회 후 랜덤하게 섞은 리스트를 계속 유지시켜야지만 구현이 가능한 것이다.
이 방식은 회원이 많아지면 많아질 수록 api를 호출할 때마다 부담이 된다고 판단하여 다른 방안을 찾아봤다.
대책 1. 페이지 마다 랜덤하게 섞기
public List<UserProfileResponseDto> getUserProfilePage(Pageable pageable){
Slice<UserInfo> users = userService.findPageBy(pageable);
List<UserProfileResponseDto> responseDtoList = users.stream()
.map(user -> toUserProfileResponseDto(user,Collections.emptySet()))
.collect(Collectors.toList());
Collections.shuffle(responseDtoList);
return responseDtoList;
}
위의 코드는 회원 전체 리스트를 페이지 별로 나눈 뒤 페이지를 랜덤하게 섞는 코드이다.
해당 코드의 문제점은 새로고침을 해도 페이지별 데이터는 같다는 것이다. 단지 페이지 마다의 데이터 순서가 달라질 뿐...
대책 2. 페이지 요청 때 마다 회원 전체 조회 후 랜덤하게 뿌려주기
public List<UserProfileResponseDto> getUserProfilePage(Pageable pageable) {
{
// 전체 사용자 정보를 가져옵니다.
List<UserInfo> allUsers = userService.findAll();
// 사용자 리스트를 셔플합니다.
Collections.shuffle(allUsers);
// 셔플된 리스트에서 페이징 처리합니다.
int totalUsers = allUsers.size();
int start = (int) pageable.getOffset();
int end = Math.min(start + pageable.getPageSize(), totalUsers);
// 페이징된 사용자 리스트를 가져옵니다.
List<UserInfo> pagedUsers = allUsers.subList(start, end);
return pagedUsers.stream()
.map(user -> toUserProfileResponseDto(user, Colletions.emtpySet()))
.collect(Collectors.toList());
}
해당 코드를 통해 요청이 들어올때마다 전체 리스트를 조회 후 섞은 뒤 리스트를 쪼개서 보내주는 코드를 생각해봤지만 사실성 요청 전 0페이지와 요청 후 1페이지의 값이 같을 수 있기 때문에 봤던 데이터를 또 볼 수도 있는 것이다. 또한 요청마다 전체 조회는 성능 저하를 일으킬 수 있기에 적용하지 못한다 판단하였다.
결론
public List<UserProfileResponseDto> getUserProfilePage(Pageable pageable){
Slice<UserInfo> users = userService.findPageBy(pageable);
List<UserProfileResponseDto> responseDtoList = users.stream()
.map(user -> toUserProfileResponseDto(user,Collections.emptySet()))
.collect(Collectors.toList());
Collections.shuffle(responseDtoList);
return responseDtoList;
}
결론은 기존 코드를 사용하며 프론트 쪽에서 랜덤을 표현하기로 했다.
서버에서는 페이지 별로 랜덤하게 섞어서 보내주고, 프론트에서는 중복없이 랜덤한 페이지 번호를 요청하도록 구현했다.