무한 스크롤 만들기

왜 ?

어떤 포스트를 통해 알게된 것이 있는데 그 내용은 다음과 같았다. 쇼핑몰에서 상품 페이지를 나타날 때 사용하는 가장 대표적인 방법들은 숫자형 페이지 버튼 vs 더보기 버튼 vs 무한스크롤이 있고, 이렇게 했을 때 사용자가 가장 오래 머무르고 상품을 많이 탐색하는 방식은 무한 스크롤방식이라고 한다. 앞선 페이지 버튼을 이용하는 부분은 많이 구현해보았으니 한번 무한 스크롤을 이용해서 데이터를 로드하는 방법을 만들어보고자 한다.

원하는 동작

  • 스크롤을 가장 아랫부분까지 내리게 되면 이벤트가 발생한다.
  • 그 이벤트를 이용해서 데이터를 추가적으로 로드한다.
  • 가져온 데이터를 페이지에 다시 추가해준다.

구현

  1. Controller 구현

    @Controller
    @Slf4j
    public class TestController {
       
        @GetMapping("/getData")
        @ResponseBody
        public List<Integer> getData(@RequestParam int page) {
            int start = (page * 10) + 1;
            int end = start + 10;
       
            log.info("page={}, {}..{}",page,start,end);
       
            List<Integer> list = new ArrayList<>();
            for (int i = start; i < end; i++) {
                list.add(i);
            }
       
            return list;
        }
       
        @GetMapping("/TestPage")
        public String getPage(){
            return "TestPage";
        }
       
    }
    
  2. 테스트 페이지 만들기(스크롤이 생기게 화면을 축소해도 되고, 내용을 많이 채워도 되고..)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>
        <script src="https://code.jquery.com/jquery-3.4.1.min.js"
                integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
                crossorigin="anonymous"></script>
        <title>테스트페이지</title>
    </head>
    <body>
        <div id="content">
            <h1 v-for="x in 20"></h1>
        	<h2 v-for="data in dataList"></h2>
        </div>
    <script>
        var list = new Vue({
           el: '#content',
           data: {
               page: 0,
               dataList: [0,1,2,3,4,5,6,7],
           }
        });
    </script>
    </body>
    </html>
    
  3. 무한 스크롤 함수 만들기

    무한 스크롤을 만들기 위해서는 아래의 사진을 이해할 필요가 있다.

    사진의 노랑색 부분의 길이는 document의 height,

    사진의 파랑색 부분의 길이가 window의 height,

    사진의 초록색 부분의 길이가 window의 scrollTop이다.

    (스크롤 길이를 표현하는게 아니라 문서의 길이)

     function infiniteScroll() {
             if ($(document).height() - 10<= $(window).height() + $(window).scrollTop()) {
                 //페이지 증가
                 list.page += 1;
                 $.ajax({
                     url: '/getData?page='+list.page,
                     type: 'GET',
                     contentType: "application/json",
                     success: function(data){
                         console.log(data);
                         for(var i=0;i<data.length;i++)
                             list.dataList.push(data[i]);
                     }
                 })
             }
         }
        
     $(document).read(function(){
        $(window).scroll(infiniteScroll) 
     });
    
  4. HTML 전체 내용

     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <script src="https://cdn.jsdelivr.net/npm/vue"></script>
         <script src="https://code.jquery.com/jquery-3.4.1.min.js"
                 integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
                 crossorigin="anonymous"></script>
         <title>테스트페이지</title>
     </head>
     <body>
         <div id="content">
             <h1 v-for="x in 20"></h1>
         	<h2 v-for="data in dataList"></h2>
         </div>
     <script>
         var list = new Vue({
            el: '#content',
            data: {
                page: 0,
                dataList: [0,1,2,3,4,5,6,7],
            }
         });
        
         function infiniteScroll() {
             if ($(document).height() - 10<= $(window).height() + $(window).scrollTop()) {
                 //페이지 증가
                 list.page += 1;
                 $.ajax({
                     url: '/getData?page='+list.page,
                     type: 'GET',
                     contentType: "application/json",
                     success: function(data){
                         console.log(data);
                         for(var i=0;i<data.length;i++)
                             list.dataList.push(data[i]);
                     }
                 })
             }
         }
        
         $(document).ready(function(){
             $(window).scroll(infiniteScroll)
         });
     </script>
     </body>
     </html>
    
  5. 구현 확인하기

    스크롤을 내려가면서 10개씩 추가되는지 확인한다.