본문 바로가기

Publishing

무한 스크롤(Infinity Scrolling) 예제 6가지

무한 스크롤(Infinity Scrolling) 예제/구현 6가지

원본은 이곳입니다. 아래는 번역입니다. 오타 및 오역은 댓글로 알려주세요. 

인피니티 스크롤은 이제 흔한 기능이고 실제로 유용하게 사용되는 사례들을 찾을 수 있습니다. 우리가 페이지를 매기는 시스템을  쉽게 생각하기 힘든 몇몇 웹사이트들, 예를 들어 트위터나 페이스북같은 사이트들이죠. 다른 예로 인피티니 스크롤은 검색엔진에서도 유용하게 사용될 수 있습니다: 사용자가 원하는 링크를 찾지 못했을 때 계속해서 새로운 결과를 찾고 싶다면, 페이징 시스템은 검색속도를 늦출 것입니다.

만약 당신이 프로젝트에 인피니티 스크롤을 사용하고 싶다면, 여기 영감을 얻고 발전시킬 수 있는 6개의 데모가 있습니다.

마지막 예제를 제외하고 나머지는 jQuery로 쓰여졌거나 어떤 예제는 jQuery 플러그인을 사용함을 유의하세요. 하지만, 마지막 예제는 바닐라 JavaScript에서 아무 문제없이 쉽게 돌릴 수 있습니다.

1. 인피니티 스크롤과 Grids

이 예제는 jQuery Masonry plugin 과 Infinite Scroll plugin 을 함께 사용합니다.Masonry plugin 은 fluid grid layout을 얻는데 적합합니다. Paul Irish의 Infinite Scroll plugin은 이미 존재하는 페이지들을 로드하는데 좋습니다(그래서 SEO (Search Engine Optimization, 검색엔진 최적화)에 좋습니다.). 당신은 page2.htmlpage3.html, 기타 등등 정적 페이지를 로드하는데 이를 사용할 수 있습니다. 이 플러그인은 또한 page.php?p=2page.php?p=3 과 같이 URL에서 페이지 숫자가 증가하는 형식에서도 사용할 수 있습니다. 하지만 page.php?data=xxx, 과 같은 형식에서 사용하고 싶다면 이건 패스하세요.

Usage – HTML

1
2
3
4
5
6
7
8
9
10
11
<div class="grid">
    <div class="grid-item grid-item-2">
        <p>content</p>
    </div>
    …
</div>
 
<!--스크롤될 때 다음 페이지 컨텐츠가 로드됩니다. -->
<nav id="pagination">
    <p><a href="page-2.html">Page 2</a></p>
</nav>
cs

Usage – jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$(document).ready(function() {
    var grid = $('.grid');
 
    grid.masonry({
        itemSelector: '.grid-item',
        columnWidth: 200
    });
 
    grid.infinitescroll({
        // Pagination element that will be hidden
        navSelector: '#pagination',
 
        // Next page link
        nextSelector: '#pagination p a',
 
        // Selector of items to retrieve 
        itemSelector: '.grid-item',
 
        // Loading Message 
        loadingText: 'Loading new items…'
    },
 
    // Function called once the elements are retrieved
    function(new_elts) {
        var elts = $(new_elts).css('opacity'0);
 
        elts.animate({opacity: 1});
        grid.masonry('appended', elts);
    });
});
cs

2. 블로그 게시물을 통한 인피니티 스크롤

이 예제는 인피니티스크롤을 다루기 위해 플러그인이나 라이브러리를 사용하지 않습니다. 사용자가 페이지 끝에 이를 때마다, 새로운 포스트를 로드하고, 해당 HTML 코드를 echo하는 PHP 스크립트를 통해 생성합니다. 이 예제는 컨텐츠 끝에 절대 도달하지는 않지만, 당신은 이것을 사용해 표시할 글이 더 이상 없을 때 문자열을 보여줄 수도 있을 겁니다. 아래는 트위터처럼 페이지 끝에 로딩 이미지를 보여줍니다.

아래 예제에서는, 새로운 포스트가 JavaScript function에 의해 생성됩니다. PHP script는 CodePen에서 사용할 수 없거든요.

Usage – HTML

1
2
3
4
5
6
7
8
9
10
11
<ul id="posts">
    <li>
        <article>content</article>
    </li>
 
    …
</ul>
 
<p id="loading">
    <img src="images/loading.gif" alt="Loading…" />
</p>
cs

Usage – jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$(document).ready(function() {
    var win = $(window);
 
    // Each time the user scrolls
    win.scroll(function() {
        // End of the document reached?
        if ($(document).height() - win.height() == win.scrollTop()) {
            $('#loading').show();
 
            $.ajax({
                url: 'get-post.php',
                dataType: 'html',
                success: function(html) {
                    $('#posts').append(html);
                    $('#loading').hide();
                }
            });
        }
    });
});
cs

3. 이미지를 통한 인피니티 스크롤

이 예제는 인피니티 스크롤로 이미지를 로드합니다. 끝이 없어요. 이것은 화면 하단에서 로딩되는 픽셀의 x값을 트리거하도록 커스트마이즈 가능한 jQuery Endless Scroll plugin을 사용합니다. 아래 예제는 동일한 이미지를 복사하고 목록 끝에 삽입하고 있지만 스크립트는 다른 소스에서 이미지를 로드하도록 꽤 쉽게 바꿀 수 있습니다.

Usage – HTML

1
2
3
4
5
6
7
8
9
<ul id="images">
    <li>
        <a href="https://www.pexels.com/photo/mist-misty-fog-foggy-7919/">
            <img src="https://pexels.imgix.net/photos/7919/pexels-photo.jpg?fit=crop&w=640&h=480" alt="" />
        </a>
    </li>
 
    …
</ul>
cs

Usage – jQuery

1
2
3
4
5
6
7
8
9
$(document).ready(function() {
    $(window).endlessScroll({
        inflowPixels: 300,
        callback: function() {
            var $img = $('#images li:nth-last-child(5)').clone();
            $('#images').append($img);
        }
    });
});
cs

4. 숫자의 Infinity List

이 예제는 이전 플러그인과 동일한 플러그인을 사용하지만, 자체 스크롤바가 있는 목록에 인피니티 스크롤을 적용했습니다. 아래로 스크롤하면 숫자가 리스트 아이템으로 추가됩니다.

Usage – HTML

1
2
3
4
5
6
7
8
<ul id="numbers">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    …
</ul>
cs

Usage – jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
$(document).ready(function() {
    var offset = $('#numbers li').length;
 
    $('#numbers').endlessScroll({
        fireOnce: false,
        fireDelay: false,
        loader: '',
        insertAfter: '#numbers li:last',
        contentfunction(i) {
            return '<li>' + (i + offset) + '</li>';
        }
    });
});
cs

5. Infinite 스프레드시트

이 예제에서는 2번과 동일한 기술을 사용해서 사용자가 문서의 끝에 도달했을 때를 감지합니다. 수직 뿐만 아니라 수평도 감지하구요. 한쪽 끝에 도달 할 때마다 테이블에 새로운 행이나 열을 추가합니다. 스프레드시트 어플리케이션을 만들려는 경우 쓰는 것과 같은 스크립트입니다.

모든 셀은 비어 있음에 유의하시고, 행과 열 인덱스는 CSS counters로 생성되므로 직접 계산할 필요가 없습니다.

Usage – HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
<table id="spreadsheet">
    <tr>
        <td></td>
        <th></th>
        …
    </tr>
    <tr>
        <th></th>
        <td></td>
        …
    </tr>
    …
</table>
cs

Usage – jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$(document).ready(function() {
    var win = $(window);
    var doc = $(document);
 
    // Each time the user scrolls
    win.scroll(function() {
        // Vertical end reached?
        if (doc.height() - win.height() == win.scrollTop()) {
            // New row
            var tr = $('<tr />').append($('<th />')).appendTo($('#spreadsheet'));
 
            // Current number of columns to create
            var n_cols = $('#spreadsheet tr:first-child th').length;
            for (var i = 0; i < n_cols; ++i)
                tr.append($('<td />'));
        }
 
        // Horizontal end reached?
        if (doc.width() - win.width() == win.scrollLeft()) {
            // New column in the heading row
            $('#spreadsheet tr:first-child').append($('<th />'));
 
            // New column in each row
            $('#spreadsheet tr:not(:first-child)').each(function() {
                $(this).append($('<td />'));
            });
        }
    });
});
cs

6. 인피니티 스크롤 + 페이지 매기기

인피니티 스크롤에는 단점이 있습니다: 만약 구현이 잘 안됐다면 사용자 경험이 박살날 거에요. 만약 유저가 무한한 목록을 로드하고 있으면, 잠시 후 유저는 길을 잃을 수도 있어요. 이건 전통적인 페이지 표시 시스템에선 절대 없을 일이죠. 하지만, 페이지 표시 시스템에선 인피니티 스크롤링에선 필요없는 유저의 액션을 요구하죠. (페이지넘버를 찾고 클릭하는 행동을 말하는 듯.)

이 두 사실은 Tim Severien에게 아이디를 제공했습니다. 인피니티 스크롤과 페이지 표시 시스템의 장점을 가져다 합치면 어떨까요? 그 결과가 이 마지막 예제입니다.

사용자가 아래로 스크롤해 페이지 하단에 도달하면 새 페이지가 자동으로 로드됩니다. 여기서 우리는 인피니티 스크롤의 단순함을 즐기죠. 근데 사실 새로운 요소들은 화면 하단에 고정된 리스트에서 옵니다. 

초기엔 숨겨져 있고, 이 리스트는 새 페이지가 로드될 때마다 이 페이지의 번호로 채워집니다. 이렇게 하면 사용자가 두 번째 페이지를 검색하려고 할 때 쉽게 해당 번호를 누르기만 하면 되죠.

Usage – HTML

1
2
<div class="article-list" id="article-list"></div>
<ul class="article-list__pagination article-list__pagination--inactive" id="article-list-pagination"></ul>
cs

Usage – JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
function getPageId(n) {
    return 'article-page-' + n;
}
 
function getDocumentHeight() {
    const body = document.body;
    const html = document.documentElement;
    
    return Math.max(
        body.scrollHeight, body.offsetHeight,
        html.clientHeight, html.scrollHeight, html.offsetHeight
    );
};
 
function getScrollTop() {
    return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
 
function getArticleImage() {
    const hash = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
    const image = new Image;
    image.className = 'article-list__item__image article-list__item__image--loading';
    image.src = 'http://api.adorable.io/avatars/250/' + hash;
    
    image.onload = function() {
        image.classList.remove('article-list__item__image--loading');
    };
    
    return image;
}
 
function getArticle() {
    const articleImage = getArticleImage();
    const article = document.createElement('article');
    article.className = 'article-list__item';
    article.appendChild(articleImage);
    
    return article;
}
 
function getArticlePage(page, articlesPerPage = 16) {
    const pageElement = document.createElement('div');
    pageElement.id = getPageId(page);
    pageElement.className = 'article-list__page';
    
    while (articlesPerPage--) {
        pageElement.appendChild(getArticle());
    }
    
    return pageElement;
}
 
function addPaginationPage(page) {
    const pageLink = document.createElement('a');
    pageLink.href = '#' + getPageId(page);
    pageLink.innerHTML = page;
    
    const listItem = document.createElement('li');
    listItem.className = 'article-list__pagination__item';
    listItem.appendChild(pageLink);
    
    articleListPagination.appendChild(listItem);
    
    if (page === 2) {
        articleListPagination.classList.remove('article-list__pagination--inactive');
    }
}
 
function fetchPage(page) {
    articleList.appendChild(getArticlePage(page));
}
 
function addPage(page) {
    fetchPage(page);
    addPaginationPage(page);
}
 
const articleList = document.getElementById('article-list');
const articleListPagination = document.getElementById('article-list-pagination');
let page = 0;
 
addPage(++page);
 
window.onscroll = function() {
    if (getScrollTop() < getDocumentHeight() - window.innerHeight) return;
    addPage(++page);
};
cs

마치며

인피니티 스크롤을 구현하는 여섯가지 예제를 살펴봤습니다. 만드려는 것에 상관없이, 이러한 테크닉 중 하나를 써서 원하는 결과를 얻으시길 바랄게요!