JPA-QueryMethods-Paging

이종찬·2023년 2월 21일
0

📖 Paging?

Paging은 검색 결과를 페이지 단위로 분할하여 반환하는 기능을 의미합니다.

Paging을 사용하면 큰 데이터셋을 처리할 때 전체 데이터를 한 번에 가져와서 처리하는 것 보다 효율적인 방식으로 처리할 수 있습니다. 해당 클래스를 사용하려면 Pageable 파라미터를 메서드에 추가해야 합니다.

Pageable 파라미터에는 페이지 번호, 페이지 크기, 정렬 정보 등을 저장할 수 있습니다. 이러한 정보로 적절한 페이지 단위로 검색 결과를 반환할 수 있습니다.

페이지 별로 검색 결과를 반환하는 예시

Page<Book> findByName(String name, Pageable pageable);

QueryMethods에서는 Slice 파라미터를 사용하여 Paging을 구현할 수도 있습니다.

Slice

Pageable과 다른점은 총 페이지 수를 반환하지 않고, 이전 페이지와 다음 페이지가 있는지 여부만 반환합니다. 해당 파라미터를 사용하게 되면 전체 페이지를 가져오는 것보다 메모리 사용이 적어 대규모 데이터 검색에 용이합니다.

🤔 사용해야 하는 이유는?

Paging을 사용하면 대량의 데이터를 작은 단위로 분할하여 처리할 수 있습니다. 대규모 데이터를 한 번에 가져와 처리하면 메모리 사용량이 한번에 크게 증가할 수 있어 성능 저하 및 서버 부하로 이어질 수 있습니다. 일정한 크기로 데이터를 분할 처리하는 Paging으로 메모리 사용량을 줄일 수 있습니다.

메모리 사용량 감소는 응답 속도 개선으로 이어집니다. 메모리 부하가 없어도 대량의 데이터를 불러오는데 시간이 오래걸려 대기시간이 증가할 수 있습니다. Paging을 이용하여 이용자가 한번에 필요한 데이터만 제공받으면 대기 시간을 최소화 할 수 있습니다.

❌ 문제가 되는 경우

1. Paging 변경

Paging된 결과가 변경이 발생하는 경우 문제가 될 수 있습니다. 이용자가 검색 결과를 보고 있는 동안 새로운 데이터의 추가, 삭제되는 경우 이용자가 보고 있는 데이터가 변경되어 Paging된 결과에 오류가 발생할 수 있습니다. 또한 Paging의 시작,끝점을 명확하게 지정하지 않는 경우도 포함됩니다. 1페이지씩 각각 가져오는 쿼리에서 중간에 새로운 데이터가 추가되어 첫번째 페이지의 데이터가 두번째 페이지에 포함될 수 있습니다. 이러한 문제를 방지하기 위해 Paging된 데이터에 대한 변경을 허용하지 않도록 구현하는 것이 좋습니다.

2. 쿼리 실행 속도

데이터베이스에서 Paging을 수행하는 경우, 쿼리 실행 속도가 느려지는 경우가 있습니다. 대규모 데이터셋을 처리하는 경우 페이지 수가 많아지면서 쿼리 실행 속도가 느려지는 경우가 발생할 수 있습니다. 이러한 경우 인덱스를 사용하거나 쿼리문을 재설정할 필요가 있습니다.

👨‍💻 구현

Entity

@Data
@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String description;

    private BigDecimal price;

    @ManyToOne
    private Category category;
}

Repository

public interface ProductRepository extends JpaRepository<Product, Long> {
    Slice<Product> findByCategoryId(Long categoryId, Pageable pageable);
}

Service

@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public Slice<Product> findProductsByCategoryId(Long categoryId, int page, int size) {
        PageRequest pageRequest = PageRequest.of(page, size, Sort.by("id").descending());
        return productRepository.findByCategoryId(categoryId, pageRequest);
    }
}

PageRequest 객체로 페이징 처리를 위한 정보를 저장한 다음 id값 기준으로 Slice객체를 반환합니다. 만약 hasNext값이 true인 경우 다음 페이지를 요청하는 방식으로 페이징 처리를 할 수 있습니다.

✅ 요약

  • Paging은 대용량의 데이터를 개발자가 설정한 대로 나뉘어 받는 형식
  • Slice는 내용에 대한 정보를 확인할 수 없으나 이전,다음 페이지와 같은 페이지의 상태에 관한 내용을 알 수 있어 페이징에 도움을 준다.
  • Paging을 사용하면 메모리 사용량 감소 -> 응답시간 최소화로 이어질 수 있다.
  • 문제가 되는 경우는 페이징의 결과를 변경하여 이용자가 보고 있는 데이터가 변경되는 것과 페이징으로 인한 쿼리 실행 속도 감소가 있다.
profile
왜? 라는 질문이 사라질 때까지

0개의 댓글