Spring Boot/A-ger프로젝트 탄생의비화

spring-boot 프론트엔드와 무한 스크롤 구현 하기[ep.2]

뇌장하드 2022. 1. 17. 11:41

spring-boot 프론트엔드와 무한 스크롤 구현 하기[ep.1]

 

spring-boot 프론트엔드와 무한 스크롤 구현 하기[ep.1]

왼쪽은 페이징 표시 오른쪽은 무한 스크롤 기능입니다. 페이징 표시는 웹에서 사용하기 적합하지만 현재 만들고 있는 서비스는 모바일 웹에 특화된 서비스 이므로 무한 스크롤 기능을 적용을

thisisthat-it.tistory.com

지난번에 구현한 페이징 처리는 정말 단순하게 페이지 처리만 해준것입니다.

문제점이 있다면 사용자가 조회할때 다른 사용자가 상품등록을 해주어서 DB에 상품 데이터가 1개가 추가된다는 상황에서 문제점이 발견이 됩니다.

간단하게 이해를 쉽게 하기 위해서 그림을 첨부해보겠습니다.

https://github.com/a-ger/a-ger-backend/issues/29

조회시에 다른 사용자가 상품을 등록하면 중복된 결과물을 내보낸다는 문제점을 해결하기 위해서 

프론트에서 page와 size를 보내주는 것이 아닌 productId와 size를 내보내줍니다.

productId는 프론트에서 보유중인 상품 리스트중에서 가장 작은 상품id값을 말합니다.

그다음 백엔드에서는 가장 작은 상품id보다 작은 상품 값으로 페이지 처리를 해줍니다. 최신순으로 정렬을 하기때문에 상품 Id의 값은 높은 순서대로 내보내지게 됩니다.

 

코드를 보면 이해가 쉬워질것입니다.

 

Controller

@GetMapping("/api/product")
    public ResponseEntity<ListResult<ProductResponse>> getlistAllProducts(
            @RequestPart(value = "productId") Long productId,
            @RequestPart(value = "size") Integer size) {
        /**
         * @Method : getlistAllProducts
         * @Description :  프론트에서 리스트 중에 가장 작은 페이지아이디{productId}와 화면에 보일 갯수{size} 를넘겨준다.
         */
        return new ResponseEntity<>(responseService.getListResult(
                productService.findProductAllByCreatedAtDesc(productId,size)), HttpStatus.OK);
    }

 

Service

public List<ProductResponse> findProductAllByCreatedAtDesc(Long prductId, Integer size) {
        Pageable pageRequest = PageRequest.of(0, size);
        return ProductResponse.toProductListResponse(productRepository.findProductsByProductIdIsLessThanOrderByCreatedAtDesc(prductId,pageRequest).getContent());
    }

 

Repository

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    Page<Product> findProductsByProductIdIsLessThanOrderByCreatedAtDesc(Long productId,Pageable pageRequest);
}

 

 

Repository에서 findProductsByProductIdIsLessThanOrderByCreatedAtDesc을 만들어 주었습니다. JPA의 장점이 여기서 나오는거 같습니다 쿼리문을 안짜고도 find~~~로 쿼리문을 안짜고 java개발에 더 몰두하게 하는 부분이 좋았습니다.

 

이런식으로 로직을 짜면 프론트에서 처음에 50개의 리스트를 주고 이제 스크롤이 가장 아래에 가면 프론트에서 리스트중에서 가장 작은 아이디값을 던져주면 아이디 값을 기준으로 작은 값들을 CeateAt기준으로 역순으로 정렬후에 size만큼 보내지게 됩니다.

여기서 Pageable pageRequest = PageRequest.of(0, size); 페이지는 항상 0으로 고정을 해줍니다. 

 

이런 과정을 거치면 중복적인 결과가 나오는 불상사를 막을수 있습니다.