Jekyll에서 카테고리 페이지 나누기

처음 블로그를 생성했을 때는 jekyll이 블로그 뼈대를 너무나 간단하게 만들어주어 감탄했지만, 시작하면서 이내 jekyll을 제대로 쓰기 위해선 공부가 필요하다는 사실을 새삼 느끼게 되었다. 특히 스킨을 만들면서 jekyll이 어떤 녀석인지 조금씩 익히고 있는데 틈나는대로 여기에 요약, 정리해보고자 한다.

Jekyll로 블로그를 생성해 본 사람이라면 바로 알게 되겠지만, jekyll은 정말 기본적인 기능만 제공하고 부가적인 기능은 플러그인으로 구현해야 한다. 어찌보면 기본적으로 제공해야 하는 게 아닌가 싶은 기능도 제공하지 않는데, 페이지 나누기가 대표적이다. Jekyll에서 글목록을 생성하려면 아래와 같이 site.posts 변수를 이용해야 한다.

{% for post in site.posts %}
    <div class="post-list">
        <h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
        <p>{{ post.date | date: "%b %d, %Y" }} by {{ post.author }}</p>
    </div>
{% endfor %}

site.posts 변수는 블로그 내의 모든 글 목록을 시간 역순으로 제공하므로 위 코드는 블로그 내의 모든 글 제목과 작성 시간, 작성자를 시간 역순으로 나열해준다. 위 코드를 이용하면 간단하게 글 목록을 생성할 수 있지만, 글이 많아지면 페이지가 길어져 한번에 보기도 힘들고 페이지를 띄우는 데 걸리는 시간도 길어지기 마련이라 게시판 형태로 페이지를 나누어줄 필요가 있다.

Jekyll 3부터 jekyll-paginate 플러그인을 기본적으로 제공하므로 이를 이용해 페이지 나누기를 구현할 수 있다. 하지만 그 기능이 아주 제한적인데, 일단 카테고리나 태그별 글 목록을 생성할 수 없고 단순히 블로그 내 모든 글 목록만 생성해준다. 게다가 페이지 나누기를 이용한 글 목록 페이지를 하나 밖에 만들 수 없어서 그야말로 불편하기 이를 데 없다. 다행스럽게도 비슷한 기능을 필요로 하는 사람이 많아서인지 여러가지 다른 플러그인이 공개되어 있고 이를 이용해 카테고리별 글 목록 페이지를 구현할 수 있다. 여러 플러그인을 시도해보았으나 적용에 성공하고, 가장 만족스러운 플러그인은 jekyll-paginate-v2였으며, 이 플러그인의 적용 방법을 간단하게 정리하고자 한다.

플러그인을 설치하기 위해 먼저 _config.yml파일의 gems 목록에 아래와 같이 jekyll-paginate-v2를 추가하고 pagination 기본 설정을 기입해주어야 한다.

../_config.yml

...

gems:
    - jekyll-paginate-v2

pagination:
    enabled: true
    per_page: 2
    limit: 0
    sort_field: "date"
    sort_reverse: true

...

Gemfile의 group에도 jekyll-paginate-v2를 추가해준다.

../Gemfile

...

group :jekyll_plugins do
    gem "jekyll-paginate-v2"

...

로컬에서 플러그인을 사용하기 위해 터미널에서 bundle install 명령어를 이용해 플러그인을 설치한다.

terminal

$ bundle install

여기까지 하면 카테고리별 페이지를 생성하기 위한 준비가 끝난 것이다. 이제 각 포스트에 카테고리를 설정하고, 카테고리별 페이지를 위한 폴더를 생성해야 한다. 본 포스트에서는 Penguin 카테고리와 Bunny 카테고리를 예제로 사용하였으며, 파일 및 폴더 구조는 아래와 같다.

../

.
├── _layouts
|   ├── default.html
|   ├── blog.html
|   └── post.html
├── _posts
|   ├── 2017-06-01-Emperor_Penguin.md
|   ├── 2017-06-01-Dutch_Bunny.md
|   ├── 2017-06-03-Rock_Hopper_Penguin.md
|   ├── 2017-06-05-Gentoo_Penguin.md
|   └── 2017-06-07-Holland_Lop_Bunny.md
├── Penguin
|   └── index.html      # Penguin 카테고리 페이지
├── Bunny
|   └── index.html      # Bunny 카테고리 페이지
├── _config.yml
├── Gemfile
└── index.html

각 카테고리 페이지는 상단 YAML front matter에 pagination 정보를 기입하는 것을 제외하면 기본 paginate 플러그인을 사용할 때와 같이 작성해주면 된다.

../Penguin/index.html

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
---
title: Penguins
layout: blog
pagination:
    enabled: true
    category: Penguin
    per_page: 2
---

{% for post in paginator.posts %}
    <div class="post-list">
        <h2><a href="{{ post.url }}" class="link-post_list">{{ post.title }}</a></h2>
        <p class="post-meta">{{ post.date | date: "%b %d, %Y" }} by {{ post.author }}</p>
        <div class="post-list-content">
            {{ post.excerpt | truncatewords: 45, '...' }}
            <p class="text-right"><a href="{{ post.url }}">read more...</a></p>
        </div>
    </div>
{% endfor %}

{% if paginator.total_pages > 1 %}
    <div class="pagination">
        {% if paginator.previous_page %}
            <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">&laquo; Prev</a>
        {% else %}
            <span>&laquo; Prev</span>
        {% endif %}

        {% for page in (1..paginator.total_pages) %}
            {% if page == paginator.page %}
                <em>{{ page }}</em>

            {% elsif page == 1 %} 
                <a href="{{ '/Penguin/index.html' | prepend: site.baseurl }}">{{ page }}</a>
            {% else %}
                <a href="{{ site.paginate_path | prepend: '/Penguin/' | prepend: site.baseurl | replace: '//', '/' | replace: ':num', page }}">{{ page }}</a>     
                <!-- 페이지 번호를 나타내기 위한 코드. -->
            {% endif %}
        {% endfor %}

        {% if paginator.next_page %}
            <a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Next &raquo;</a>
        {% else %}
            <span>Next &raquo;</span>
        {% endif %}
    </div>
{% endif %}

Bunny 카테고리 페이지도 마찬가지로 작성해주면 된다. 여러 카테고리 페이지를 만들고자 할 경우 레이아웃을 만들어두고 참조하는 형태로 사용하는 것이 적절하지만, 일부 path 설정이 잘 되지 않아1 각 카테고리별로 페이지를 따로 작성하였다. 위 코드의 36, 38번째 줄을 보면 카테고리에 따라 path를 따로 지정해둔 것을 볼 수 있다.

  1. Permalink 설정에 문제가 있는 듯 보인다.