네이버 이웃 추가 / GitHub Profile / 카카오톡 채널 추가 / 방명록 / 이용 안내

[Jekyll 블로그 구축 일기]2. 테마 수정하기

수성컴 | 2023. 07. 08.
[Jekyll 블로그 구축 일기]2. 테마 수정하기

수성컴전자방입니다. 오늘은 Jekyll 블로그 테마 수정(소스코드 수정) 과정을 기록해 보겠습니다. 기본적인 HTML 지식을 가지고 이 글을 읽으시기를 권장합니다. 저는 사실 테마를 처음부터 만들었으므로 글이 굉장히 깁니다. 필요하신 부분만 발췌하여 읽으시기 바랍니다.

목차

1. Ruby와 Jekyll 설치

2. 테마 수정하기(이번 글)
2.1. 기본적으로 알아두어야 할 것
2.2. config.yml 수정하기
2.3. _layouts/default.html (layout 사용 방법)
2.4. assets/css/stylesheet.scss

2.5. 반응형 웹을 위한 assets/js/jsfunc.js
2.5.1. 사이드바 버튼 관련 _layouts/default.html
2.5.2. 사이드바 버튼 관련 assets/css/stylesheet.scss

2.6. _layouts/post.html
2.6.1. 관련 assets/css/stylesheet.scss

2.7. _layouts/page.html, _layouts/home.html

2.8. _includes/sidebar/sidebar1.html, _includes/sidebar/sidebar2.html (include 사용 방법)
2.8.1. 사이드바 관련 _layouts/default.html
2.8.2. 사이드바 관련 assets/css/stylesheet.scss

2.9. 카테고리 기능 구현
2.9.1. 카테고리 관련 _config.yml
2.9.2. _includes/archive_single.html
2.9.3. _layouts/category_page.html
2.9.4. 메타태그 관련 _layouts/default.html
2.9.5. 각 카테고리 페이지 파일
2.9.6. _includes/sidebar/category_list.html
2.9.7. category list 관련 _includes/sidebar/sidebar1.html
2.9.8. category list 관련 assets/css/stylesheet.scss
2.9.9. category list 결과

2.10. 글(post) 작성 방법
2.10.1. 글 permalink 관련 _config.yml

2.11. 코드블록(highlight.js)
2.11.1. 코드블록 관련 layouts/post.html
2.11.2. 코드블록 관련 stylesheet.scss

2.12. 이미지 클릭 시 새 탭으로 열기를 위한 _includes/jsscript.html
2.12.1. 이미지 클릭 시 새 탭으로 열기 관련 _layouts/post.html
2.12.2. 이미지 클릭 시 새 탭으로 열기 관련 assets/css/stylesheet.scss
2.12.3. 이미지 클릭 시 새 탭으로 열기 결과

2.13. 검색 기능(jekyll-tipue-search)
2.13.1. search.html 수정
2.13.2. _includes/sidebar/search.html
2.13.3. 검색 기능 관련 _layouts/default.html
2.13.4. 검색 기능 관련 _includes/sidebar/sidebar1.html
2.13.5. 검색 기능 관련 assets/css/stylesheet.scss
2.13.6. 검색 기능 관련 _config.yml

2.14. Pagination(페이지 나누기)
2.14.1. Pagination 관련 _config.yml
2.14.2. Pagination 관련 Gemfile
2.14.3. Pagination을 위해 index.markdown → index.html
2.14.4. Pagination 관련 _layouts/home.html와 _layouts/category_page.html
2.14.5. Pagination 관련 assets/css/stylesheet.scss
2.14.6. Pagination 관련 각 카테고리 html 파일 머리말 수정

2.15. 404.html, about.markdown
2.16. rss
2.17. sitemap 플러그인으로 sitemap.xml 만들기
2.18. robots.txt

2.19. _includes/og.html
2.19.1. Open Graph 관련 _layouts/default.html

2.20. 글 마무리
2.21. 참고 자료

2.1. 기본적으로 알아두어야 할 것

여기 있는 것들은 기본적인 사항들입니다. 읽어 보시고 이해가 안 된다면 2.2절 이하 본문을 먼저 읽어 보시고 다시 여기를 보시면 이해가 될 것입니다.

  • 용어 정리
    • Ruby: 프로그래밍 언어
    • Liquid: Ruby 기반 템플릿 언어
    • Jekyll: 블로그 엔진. 페이지에 Liquid 태그를 사용하면 Jekyll 엔진이 정적 페이지로 빌드해 줍니다.
    • GitHub, GitLab: Jekyll 블로그를 호스팅할 수 있는 플랫폼
  • 파일 서두에 --- 두 줄을 입력하면 빌드 대상이 됩니다. --- 두 줄 사이에는 머리말(Front Matter)을 YAML(yml) 형태로 입력할 수 있습니다.
---
여기에 머리말(Front Matter)을 YAML 형태로 작성
---
그 아래 content(markdown 또는 html) 작성. Liquid 태그 사용 가능.
  • assets 폴더 안에 있는 파일은 서두에 --- 두 줄이 없어도(빌드를 안 해도) 사이트로 배포 가능.
    assets 폴더 밖에 있는 파일은 서두에 --- 두 줄이 없으면 사이트에 포함 안 됨.(빌드해야 배포 가능)
  • _layouts 폴더 안에는 layout들을 넣습니다. → 본문이 들어갈 자리에 {{content}} 작성. 해당 layout을 사용하려면 페이지의 머리말에서 layout 설정.
    • 예) _layouts/post.html을 쓰려면 페이지의 머리말에 layout: post.html 작성.
    • 자세한 정보는 2.3절 참고
  • _includes 폴더 안에는 자주 사용할 템플릿을 넣습니다. → 해당 템플릿을 사용하려면 {% include 파일 경로 %}
    • 예) _includes/footer.html을 쓰려면 페이지의 해당 부분에 {% include footer.html %} 작성
    • 자세한 정보는 2.8절 참고
  • _posts 폴더 안에는 글을 작성합니다.
  • _site 폴더 안에는 빌드 결과 생성된 파일들이 저장됩니다.(우리는 건드릴 필요 없음.)
  • 그 밖에 원하는 폴더를 만들어 사용할 수 있습니다. 단, 이 경우 폴더명이 underscore(_)로 시작하면 안 됩니다.
  • 권장 폴더 구조(굵은 글씨는 폴더)
    • assets
      • css
      • images
      • js
    • _includes
    • _layouts
    • _posts
    • index.html
    • _config.yml
    • Gemfile
    • 기타 등등

2.2. config.yml 수정하기

지금 완전히 수정하려는 것은 아니고, 기본적인 블로그 정보를 작성해 보겠습니다.

# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
#
# If you need help with YAML syntax, here are some quick references for you:
# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
# https://learnxinyminutes.com/docs/yaml/
#
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.

title: 수성컴전자방 # 여기에 블로그 이름 입력
email: aaa@bbb.com # 여기에 전자 우편 주소 입력
description: >- # this means to ignore newlines until "baseurl:" 왠만하면 description 중간에는 큰따옴표 쓰지 마세요.
  개발 블로그 '수성컴전자방'입니다.
baseurl: "" # the subpath of your site, e.g. /blog  저는 안 썼습니다.
url: "https://sooseongcom.com" # the base hostname & protocol for your site, e.g. http://example.com
# twitter_username: jekyllrb 저는 트위터 계정이 없어서 입력 안 했습니다.
github_username:  # 여기에 GitHub username 입력

# Build settings
theme: # 비워 두세요.
plugins:  # 이건 나중에 수정할게요.
  - jekyll-feed

# permalink for posts
permalink: "post/:title"

# category
categories_main: [정보, 프로그래밍, 수성컴의_작품]
categories_information: [Windows, 안드로이드(일반), 안드로이드(앱), 라즈베리파이, 정보_기타]
categories_programming: [VS_Code, Git, 웹개발, C++, Verilog, 프로그래밍_기타]
categories_esd: [절정_및_오피스, 웹사이트_및_웹앱, 작품_기타]

# Exclude from processing.
# The following items will not be processed, by default.
# Any item listed under the `exclude:` key here will be automatically added to
# the internal "default list".
#
# Excluded items can be processed by explicitly listing the directories or
# their entries' file path in the `include:` list.
#
# exclude:
#   - .sass-cache/
#   - .jekyll-cache/
#   - gemfiles/
#   - Gemfile
#   - Gemfile.lock
#   - node_modules/
#   - vendor/bundle/
#   - vendor/cache/
#   - vendor/gems/
#   - vendor/ruby/

위에 있는 것은 예시입니다. 여러분 상황에 맞게 수정해서 쓰세요. YAML이기 때문에 JSON과 달리 띄어쓰기가 없는 한 큰따옴표를 안 써도 됩니다. 다음에 _config.yml을 보여드릴 때에는 일부 주석은 생략하고 보여드릴 것이니 유의하시기 바랍니다.

2.3. _layouts/default.html

일단 처음에는 _layouts 폴더가 없을 것입니다. root directory에 _layouts 폴더를 만듭니다.(여기서 말하는 root는 리눅스 컴퓨터의 root가 아니라 프로젝트(블로그)의 root(최상위)입니다.)

그 다음 _layouts 폴더 안에 default.html 파일을 만들고 블로그 페이지의 기본적인 틀을 만듭니다.

---

---

<!DOCTYPE html>
<html>

<head>
    <title>{% if page.title %}{{page.title}} | {% endif %} {{site.title}}</title>
    <link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico?"/>
    <link rel="stylesheet" href="/assets/css/stylesheet.css">
    <link rel="alternate" type="application/rss+xml" title="수성컴전자방" href="https://sooseongcom.com/rss"/>
    <meta charset="utf-8" />
    <meta name="viewport" content="user-scalable=no,width=device-width,initial-scale=1.0">
</head>

<body>

<header>
    <div id="sidebar_button">
        <div class="sidebar_button_pc">
            <a href="javascript:viewLayerSidebarPC();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
        <div class="sidebar_button_tab">
            <a href="javascript:viewLayerSidebarTab();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
        <div class="sidebar_button_mobile">
            <a href="javascript:viewLayerSidebarMobile();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
    </div>
    <div id="top_title">
        <div class="top_title_pc">
            <a href="/">
                <img src="/assets/images/soojaimage.png" alt="수성컴전자방"/>
            </a>
        </div>
        <div class="top_title_mobile">
            <a href="/">
                <img src="/assets/images/soojaimage_m.png" alt="수성컴전자방_m"/>
            </a>
        </div>
    </div>
</header>

<div id="main">
    <div id="sidebar1">
        사이드바1(왼쪽) 부분
    </div>
    <div id="sidebar2">
        사이드바2(오른쪽) 부분
    </div>
            
    <div id="content">
        {{content}}
    </div>
</div>

<footer>
    <div id="footer_content">
        <p>수성컴전자방 Sooseongcom</p>
        <p>Only some of text/picture licence: <b>CC BY</b> (인용 목적으로 글/사진 일부 복사 시 저작자 표시)</p>
        <p>그 외 자세한 사항은 <a href="/about" target="_blank">About(새 탭에서 열림)</a>을 확인하시기 바랍니다.</p>
    </div>
</footer>

</body>

</html>

길어서 당황스러우시겠지만 차근차근 설명 드리겠습니다. head 태그 그룹부터 보겠습니다.

[Line 9]

<title>{% if page.title %}{{page.title}} | {% endif %} {{site.title}}</title>

이것을 보기 좋게 정리하면 아래와 같습니다.

<title>
  {% if page.title %}
    {{page.title}} | 
  {% endif %}
  
  {{site.title}}
</title>

title 태그 안에 Liquid 태그를 사용하였습니다. page.변수명은 최종 페이지(예: post)의 변수를 의미합니다. 위의 소스코드는 page.title이 있으면 “page.title | “을 title의 내용에 넣겠다는 뜻입니다.

site.변수명은 _config.html에서 정의한 변수를 의미합니다. 위의 소스코드에 따르면 if문 바깥에서 site.title을 넣습니다. 2.2절에서 site.title에 블로그 이름을 넣었습니다. 그러므로 최종적인 title은 아래와 같이 될 것입니다.

글 제목 | 블로그 이름

[Line 10]

<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico?"/>

파비콘을 연결합니다. 파비콘 경로는 /assets/images/favicon.ico로 했습니다.
이상하게 href를 “/assets/images/favicon.ico”로 하면 오류가 나더라고요. ico 뒤에 물음표를 붙여서 “/assets/images/favicon.ico?“로 하면 해결됩니다.

[Line 11]

<link rel="stylesheet" href="/assets/css/stylesheet.css">

stylesheet를 연결하는 부분입니다. 2.4절에서 다시 설명 드리겠습니다.

[Line 12]

<link rel="alternate" type="application/rss+xml" title="블로그 이름" href="블로그주소/rss"/>

RSS 구독 프로그램에 블로그 주소만 입력해도 알아서 블로그주소/rss가 수집되게 하는 역할을 합니다.

[Line 13]

<meta charset="utf-8" />

인코딩을 UTF-8로 합니다.

[Line 14]

<meta name="viewport" content="user-scalable=no,width=device-width,initial-scale=1.0">

반응형 웹 메타태그입니다.

이제 body 태그 그룹을 보겠습니다.
body는 HTML5 표준에 따라 header, footer 등을 나누어 작성했습니다.
수성컴전자방-page3
위의 스크린샷에서 빨간 글씨는 HTML5 표준이고, 파란 글씨는 제가 지정한 구분입니다.

[Line 19~43 header]
햄버거버튼과 수성컴전자방로고
사이드바 버튼과 수성컴전자방 로고를 넣었습니다.

<header>
    <div id="sidebar_button">
        <div class="sidebar_button_pc">
            <a href="javascript:viewLayerSidebarPC();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
        <div class="sidebar_button_tab">
            <a href="javascript:viewLayerSidebarTab();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
        <div class="sidebar_button_mobile">
            <a href="javascript:viewLayerSidebarMobile();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
    </div>
    <div id="top_title">
        <div class="top_title_pc">
            <a href="/">
                <img src="/assets/images/soojaimage.png" alt="수성컴전자방"/>
            </a>
        </div>
        <div class="top_title_mobile">
            <a href="/">
                <img src="/assets/images/soojaimage_m.png" alt="수성컴전자방_m"/>
            </a>
        </div>
    </div>
</header>

사이드바 버튼은 Pixabay에서 무료 이미지를 내려받아서 사용했습니다. 같은 이미지를 3개 넣었는데 각각 class를 sidebar_button_pc, sidebar_button_tab, sidebar_button_mobile로 했습니다. 그 이유는 javascript를 작성할 때 사용하기 위함입니다.
수성컴전자방 로고는 큰 로고와 작은 로고를 사용하여 PC와 모바일에 각각 대응하도록 했습니다. 파일명을 soojaimage.png, soojaimage_m.png로 했는데 그냥 평범하게 logo.png, logo_m.png로 할 걸 그랬습니다..
참고로 이렇게 같은 이미지를 여러 번 넣은 다음에는 CSS media 태그를 이용해서 화면 크기에 알맞은 이미지만 뜨도록 해야 합니다. 그건 2.4절에서 다루겠습니다.

[Line 46~51]
sidebar 부분입니다. include 기능을 이용할 것이므로 나중에 설명 드리겠습니다.

[Line 53~55]
layout을 만들 때 중요한 부분입니다!

<div id="content">
    {{content}}
</div>

이 layout을 사용하는 파일의 내용이 들어가는 부분입니다. layout 파일(여기서는 default.html)에 {{content}}를 작성해 주면 이 layout을 사용하는 페이지의 내용이 이 부분에 들어갑니다.

예)
▼layouts/default.html

---
---
이 부분은 layout의 공통 부분~~
<div id="content">
    {{content}}
</div>
안녕~~~~~

▼example.html

---
layout: default
---
<p>반갑습니다! 예시입니다!!</p>

▼빌드 결과

이 부분은 layout의 공통 부분~~
<div id="content">
    <p>반갑습니다! 예시입니다!!</p>
</div>
안녕~~~~~

[Line 58~64 footer]
licence
저는 저작권 안내를 넣었습니다. 어떤 분들은 이 부분에 SNS 링크들을 넣기도 합니다.

<footer>
    <div id="footer_content">
        <p>수성컴전자방 Sooseongcom</p>
        <p>Only some of text/picture licence: <b>CC BY</b> (인용 목적으로 글/사진 일부 복사 시 저작자 표시)</p>
        <p>그 외 자세한 사항은 <a href="/about" target="_blank">About(새 탭에서 열림)</a>을 확인하시기 바랍니다.</p>
    </div>
</footer>

2.4. assets/css/stylesheet.scss

일단 확장명부터 언급해야겠습니다. css는 익숙한데 scss는 생소하실 것 같습니다. 먼저, SASS(.sass)를 아는 것이 좋겠습니다. SASS는 CSS와 달리 nesting(중첩), 변수, //주석 등을 지원하므로 보다 편리하게 코딩할 수 있습니다.(참고로 CSS에서는 중첩을 표현하려면 div #main .content 같은 방식으로 해야 함.)

SASS는 확장명으로 .sass와 .scss를 지원합니다.
sass는 nesting(중첩)에서 중괄호 대신 들여쓰기와 줄바꿈을 사용합니다. Python과 비슷한 느낌입니다.
scss는 nesting(중첩)에서 중괄호를 사용합니다. CSS, C언어 등과 유사합니다. CSS를 그대로 써도 오류가 발생하지 않는다는 장점이 있습니다. 그러므로 저는 scss를 쓰겠습니다.

SASS(.sass, .scss)는 웹브라우저에서 지원하지 않으므로 CSS로 변환(컴파일)하는 과정이 필요합니다. 우리는 Jekyll 엔진을 활용하면 됩니다. 이를 위해 SASS(.sass, .scss) 파일 최상단에 --- 두 줄을 입력합니다.

제가 SASS(.sass, .scss) 파일을 둘 경로는 assets/css/stylesheet.scss입니다. 이는 권장 폴더 구조를 따른 것입니다.
scss 파일이지만 jekyll serve 하면 css가 되므로 _layouts/default.html 파일에서 연결할 때에는 아래와 같이 css 확장명으로 작성합니다.(아래 코드는 2.3절 예제의 11행입니다.)

<link rel="stylesheet" href="/assets/css/stylesheet.css"> <!--_layouts/default.html Line 11-->

이제 본격적으로 제가 작성한 assets/css/stylesheet.scss 내용을 보겠습니다. 정답이 아니고, 그냥 제 취향대로 작성한 것임을 알려드립니다. 다 보여드리면 너무 길 것 같아서 일부만 보여드리겠습니다.

일단 대략적인 구조는 아래와 같습니다.

---
---
/*
공통사항.
@import, body, h1~h6, blockquote, a, a:hover, 검색상자, img, img:hover,
article,  마무리, archive_single, #pagination_button_list, .sidebar_component,
.sidebar_title, #hyper a, .category a, .category_sub a, .category_sub,
#tipue_search_input, footer, #footer_content .
*/

@media only screen and (min-width: 1600px){    
    /*
    PC(와이드스크린)에서의 모습.
    header, #main, #sidebar1, #content, #sidebar2 등
    */
}

@media only screen and (max-width: 1600px) and (min-width: 1020px){    
    /*
    태블릿에서의 모습.
    header, #main, #sidebar1, #content, #sidebar2 등
    */
}

@media screen and (max-width: 1020px){
    /*
    모바일에서의 모습.
    header, #main, #content, #sidebar1, #sidebar2 등
    */
}

@media (prefers-color-scheme: 'dark') {
    /*
    다크모드.
    body, #sidebar1, #sidebar2, #content, blockquote, header, a, a:hover, 검색 상자, article 등의 배경색, 글자 색상.
    */
}

창 크기, 다크모드 등에 대응하는 반응형 웹으로 만들었습니다.

제가 코딩한 모든 것을 여기서 설명하면 글이 너무 길어질 것 같습니다.
이 문단에서는 h1~h6과 blockquote의 글꼴에 대해서 설명 드리겠습니다. 해당 글꼴은 GitHub를 흉내내 봤습니다.

---
---
@import url(//fonts.googleapis.com/earlyaccess/nanumgothic.css);
@import url(//fonts.googleapis.com/earlyaccess/nanumgothiccoding.css);

body {
 font-family: 'Nanum Gothic', sans-serif;
}


h1, h2, h3, h4, h5, h6 {
    margin-top: 24px;
    margin-bottom: 16px;
    line-height: 1.25;
}

h1 {
    display: block;
    font-size: 2em;
    margin-block-start: 0.67em;
    margin-block-end: 0.67em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    font-weight: bold;
}

h2 {
    padding-bottom: .3em;
    font-size: 1.5em;
    border-bottom: 1px solid hsla(210,18%,87%,1);
}

h3 { font-size: 1.25em;}
h4 { font-size: 1em;}
h5 { font-size: .875em; }
h6 { font-size: .85em; color: #57606a; }

blockquote {
    padding: 0 1em;
    color: #57606a;
    border-left: .25em solid #d0d7de;
}

a {color: #333333; text-decoration:none;}
a:hover {color: #333333; text-decoration:underline; transition: text-decoration 1s;}

//...

img {max-width: 100%;}

//...

[Line 3~4]
글꼴을 불러옵니다.

[Line 6~8]
페이지 전체에 해당하는 body 태그 그룹의 글꼴을 설정하는 부분입니다. 나눔고딕, sans-serif 순으로 적용합니다. 나눔고딕을 적용할 수 없는 상태가 되면 sans-serif가 대신 적용되는 것입니다.

[Line 11~36]
h1~h6과 blockquote는 GitHub markdown의 서식을 약간 수정해서 가져왔습니다.

[Line 44~45]
a {color: #333333; text-decoration:none;}
a:hover {color: #333333; text-decoration:underline; transition: text-decoration 1s;} 그냥 a는 하이퍼링크에 기본적으로 적용되는 글꼴이고, a:hover는 하이퍼링크에 커서를 올려 두면 적용되는 글꼴입니다. 하이퍼링크에 커서를 올려 두면 1초 내로 밑줄이 생기게 했습니다.

[Line 49]

img {max-width: 100%;}

img(이미지)의 최대 너비를 100%로 잡았습니다.

2.5. 반응형 웹을 위한 assets/js/jsfunc.js와 사이드바 버튼

모바일 화면에서는 사이드바가 숨겨져 있으며, 사용자가 버튼을 누르면 사이드바가 나타납니다. assets/js/jsfunc.js 경로로 파일을 하나 만듭니다.

function viewLayerSidebarPC(){
    if(document.getElementById("sidebar1").style.display=='none'){
        document.getElementById("sidebar1").style.display='block';
        document.getElementById("sidebar2").style.display='block';
        document.getElementById("content").style.width='940px';
    }
    else{
        document.getElementById("sidebar1").style.display='none';
        document.getElementById("sidebar2").style.display='none';
        document.getElementById("content").style.width='74%';
    }

}

function viewLayerSidebarTab(){
    if(document.getElementById("sidebar1").style.display=='none'){
        document.getElementById("sidebar1").style.display='block';
        document.getElementById("content").style.width='70%';
    }
    else{
        document.getElementById("sidebar1").style.display='none';
        document.getElementById("content").style.width='97%';
    }

}

function viewLayerSidebarMobile(){
    if(document.getElementById("sidebar1").style.display!='block'){
        document.getElementById("sidebar1").style.display='block';
    }
    else{
        document.getElementById("sidebar1").style.display='none';
    }

}

이 파일에는 3가지 함수가 정의되어 있습니다. 그 중 3번째 함수가 정의된 27~35행만 먼저 간략하게 설명 드리겠습니다.
viewLayerSidebarMobile() 함수가 호출되면 document.getElementById(“sidebar1”).style.display!=’block’ 여부를 확인합니다.
document.getElementById(“sidebar1”).style.display!=’block’이면, 즉 sidebar1이 띄워져 있지 않으면 document.getElementById(“sidebar1”).style.display=’block’;을 실행하여 sidebar1을 띄웁니다.
document.getElementById(“sidebar1”).style.display==’block’이면, 즉 sidebar1이 이미 띄워져 있으면 document.getElementById(“sidebar1”).style.display=’none’;을 실행하여 sidebar1을 닫습니다.
참고로 나머지 함수들은 display 속성 변경 외에 content의 너비 조정까지 실행합니다.

2.5.1. 사이드바 버튼 관련 _layouts/default.html

그러면 직접 정의한 javascript 함수들을 어떻게 호출할까요? HTML 파일에서 a 태그를 이용하면 됩니다.

<a href="javascript:함수명">내용</a>

위와 같은 방식으로 layouts/default.htmlheader 부분에서 적용해 보겠습니다.

<!-- layouts/default.html의 header 부분 -->
<header>
    <div id="sidebar_button">
        <div class="sidebar_button_pc">
            <a href="javascript:viewLayerSidebarPC();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
        <div class="sidebar_button_tab">
            <a href="javascript:viewLayerSidebarTab();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
        <div class="sidebar_button_mobile">
            <a href="javascript:viewLayerSidebarMobile();"><img src="/assets/images/hamburger-icon.png"></a>
        </div>
    </div>
    <!-- 이후 부분 생략 -->

위의 코드블록을 보시면 id가 sidebar_button인 div 안에 div class가 3개 있는 것을 보실 수 있습니다. 각각 PC, 태블릿, 모바일에서의 버튼입니다. 창 크기를 조절하다 보면 창 크기가 작을 때 사이트바 메뉴를 닫고 다시 창 크기를 키웠을 때 사이드바가 안 보이는 문제가 있으므로 PC화면에서도 사이드바 버튼을 만들었습니다. 각각의 div class 안에는 img 태그로 /assets/images/hamburger-icon.png을 넣습니다. 이 이미지는 일단 Pixabay에서 가져왔습니다. 나중에 바꾸게 될지도 모르겠지만요… 각각의 이미지를 a 태그로 감싸고, 각각 javascript:viewLayerSidebarPC();, javascript:viewLayerSidebarTab();, javascript:viewLayerSidebarMobile();로 연결합니다.

2.5.2. 사이드바 버튼 관련 assets/css/stylesheet.scss

이제 CSS를 수정해야 합니다.

---
---
/* 공통사항 생략 */

@media only screen and (min-width: 1600px){    
    header {
        width: 100%; height: 130px; margin: 0 0 15px 0; border-bottom: 1px solid #cccccc;
        #sidebar_button {
            float: left; height: 30%; margin: 50px 0 0 8%; padding: 13px 0 0 0;
            .sidebar_button_pc{height: 100%; display: block;}
            .sidebar_button_tab{display: none;}
            .sidebar_button_mobile{display: none;}
        }
        #top_title {
            float: left; height: 100%; margin-left: 15%; padding: 13px 0 0 0;
            .top_title_pc{height: 100%; display: block;}
            .top_title_mobile{height: 100%; display: none;}
        }
        img{float: right; height: 80%;}
    }

    //...
}

@media only screen and (max-width: 1600px) and (min-width: 1020px){    
    header {
        width: 100%; height: 130px; margin: 0 0 15px 0; border-bottom: 1px solid #cccccc;
        #sidebar_button {
            float: left; height: 30%; margin: 50px 0 0 8%; padding: 13px 0 0 0;
            .sidebar_button_pc{display: none;}
            .sidebar_button_tab{height: 100%; display: block;}
            .sidebar_button_mobile{display: none;}
        }
        #top_title {
            float: left; height: 100%; margin-left: 15%; padding: 13px 0 0 0;
            .top_title_pc{height: 100%; display: block;}
            .top_title_mobile{height: 100%; display: none;}
        }
        img{float: right; height: 80%;}
    }

    //...
}

@media screen and (max-width: 1020px){
    header {
        position: fixed; top: 0; z-index: 10; background-color: #f4f4f6;
        width: 100%; height: 35px; padding-bottom: 10px; border-bottom: 1px solid #cccccc;
        #top_title {
            float: left; height: 100%; padding: 5px 0 0 25%;
            .top_title_pc{height: 100%; display: none;}
            .top_title_mobile{
                height: 100%; display: block;
                img{float: right; height: 35px;}
            }
        }
        #sidebar_button {
            float: left; height: 80%; padding: 13px 0 0 0;
            .sidebar_button_pc{display: none;}
            .sidebar_button_tab{display: none;}
            .sidebar_button_mobile{height: 100%; margin-right: 20px; display: block;}
        }
        img{float: right; height: 100%;}
    }

    //...
}

@media (prefers-color-scheme: 'dark') {
    //...

    header{
        background-color: #c4c4c6;  //다크모드에서 이 배경색은 좀 별로인 듯.. 나중에 수정하게 될 것 같아요.
    }

    //...
}

8~13행만 설명 드리겠습니다. PC 화면에서의 설정입니다. .sidebar_button_pc는 display: block; 으로 하여 표시되게 합니다. .sidebar_button_tab, .sidebar_button_mobile은 display: none; 으로 하여 숨겨지게 합니다.
같은 방식으로 태블릿 화면에서는 .sidebar_button_tab만, 모바일 화면에서는 .sidebar_button_mobile만 보이게 코딩합니다.
다만, 모바일 화면에서는 .sidebar_button_mobile의 속성에 margin-right: 20px; 을 추가하여 블로그 로고와의 간격을 갖도록 합니다.

2.6. _layouts/post.html

글 하나 하나의 레이아웃을 만들어 보겠습니다. 먼저, _layouts 폴더 안에 post.html 파일을 생성하여 작성합니다.

---
layout: default
---

<article>
    <h1>{{page.title}}</h1>
    <div class="info">
        {{page.author}} |
        {% assign category=page.categories[0] %}
        <a href="/category/{{category}}">{{category}}</a>
        {% if page.categories[1] %}
            {% assign category=page.categories[1] %}
            ▶<a href="/category/{{category}}">{{category}}</a>
        {% endif %}
        | {{page.date | date: "%Y. %m. %d."}}
    </div>

    <!-- 중략 -->

    {{content}}

</article>

<!-- 이후 부분 생략 -->

[Line 2]
‘post’라는 layout의 layout은 ‘default‘입니다. 그래야 default.html에서 코딩한 것 안에 post가 들어갑니다.

[Line 5~22]
본문의 모든 내용은 article 태그 그룹에 들어갑니다.

[Line 6]
글 제목을 h1 태그 안에 넣습니다. h1 태그를 사용하는 이유는 SEO 최적화를 하기 위함입니다.

[Line 7~16]
글 정보에 관한 것을 표시합니다. 자세한 것은 이어서 설명하겠습니다.

[Line 9~14]
제 블로그는 카테고리가 계층 구조로 되어 있으므로 대부분의 글이 2개의 카테고리를 갖고 있습니다. 글 쓰는 방법을 알려드릴 때 설명하겠지만, 글 머리말에서 category를 배열로 선언하여 2개 입력하는 방식입니다. 그러므로 page.categories[0], page.categories[1]로 선언할 수 있습니다. 저는 if문을 사용하여 카테고리를 표현하도록 했습니다. a href에 적을 카테고리 주소는 카테고리 페이지 소스코드 작성하면서 머리말에서 지정합니다.

[Line 15]
글 쓴 날짜입니다. page.date 변수를 사용하면 글 파일명에서 날짜를 추출해서 표시할 수 있습니다. 날짜 형식을 지정하려면 | date: “형식을 뒤에 붙입니다. 날짜 형식은 아래와 같이 지정합니다.

  • %Y: 연도(네 자리)
  • %y: 연도(두 자리)
  • %m: 월
  • %d: 일

[Line 20]
{{content}} 이 부분에 글 본문이 들어갑니다.

2.6.1. 관련 assets/css/stylesheet.scss

---
---
//...

article{
    padding-bottom: 50px;

    p {margin-bottom: 20px;}
    a[target="_blank"], a:hover[target="_blank"] {color: #000070; text-decoration: underline;}
    a {color: #0969da; text-decoration: none;}
    a:hover {color: #0969da; text-decoration: underline;}

    font-size: 16px;
    line-height: 1.8;

    .info{
        width: 100%;
        font-size: 12px;
        border-bottom: 1px solid #cccccc;
        padding-bottom: 15px;
    }

    img{display: block; margin: 0 auto -1.5em auto;}

    //...
}

//...

@media only screen and (min-width: 1600px){    
    //...
}

@media only screen and (max-width: 1600px) and (min-width: 1020px){
    //...
}

@media screen and (max-width: 1020px){
    //...
}

@media (prefers-color-scheme: 'dark') {
    //...

    article{
        a[target="_blank"], a:hover[target="_blank"] {color: #00dfff; text-decoration: underline;}
        a {color: #58a6ff; text-decoration: none;}
        a:hover {color: #58a6ff; text-decoration: underline;}
    
        font-size: 16px;
        line-height: 1.8;
    
        .info{
            width: 100%;
            font-size: 12px;
            border-bottom: 1px solid #cccccc;
            padding-bottom: 15px;
        }
    
        img{display: block; margin: 0 auto -1.5em auto;}
    
        //...
    }

    //...
}

몇 가지만 설명하겠습니다.

[Line 6]

padding-bottom: 50px;

본문 아래에 50px의 padding을 갖습니다. 이는 댓글과의 간격을 갖기 위함입니다.

[Line 8]

p {margin-bottom: 20px;}

각 문단 아래에 20px의 margin을 갖습니다. markdown에서 줄바꿈을 2번 하면 실제 글에도 20px의 간격이 생기는 것입니다.

[Line 9~11] a[target=”_blank”], a:hover[target=”_blank”] {color: #000070; text-decoration: underline;}
a {color: #0969da; text-decoration: none;}
a:hover {color: #0969da; text-decoration: underline;}

a[target=”_blank”], a:hover[target=”_blank”]는 새 탭으로 열리는 링크입니다. 대괄호를 사용하면 특정 속성이 있을 때에만 적용되는 서식을 지정할 수 있습니다.
a는 현재 탭에서 열리는 링크입니다.
a:hover는 현재 탭에서 열리는 링크에 마우스를 갖다댔을 때의 서식입니다.

[Line 13~14]
font-size: 16px;
line-height: 1.8;

글자 크기는 16px, 줄 간격은 1.8로 지정했습니다.

[Line 16~21]
작성자 정보에 적용되는 서식입니다.

[Line 23]

img{display: block; margin: 0 auto -1.5em auto;}

이미지를 좌우 가운데 정렬하고 아래 margin을 -1.5em 적용합니다. 아래 margin이 -1.5em 적용된 이유는 이미지와 그 아래 문단 사이 간격을 좁히기 위해서입니다.

2.7. _layouts/page.html, _layouts/home.html

---
layout: default
---

{{content}}

일단 둘 다 위와 같은 내용으로 파일을 만듭니다. 그러면 이제 jekyll serve 명령어로 서버를 실행했을 때 지금까지 작업한 내용을 확인하실 수 있는 정도는 되는 것입니다.

2.8. _includes/sidebar/sidebar1.html, _includes/sidebar/sidebar2.html

저는 좌우에 사이드바를 하나씩 놓기 때문에 사이드바 파일이 2개인 것입니다. 사이드바를 1개 쓰실 분은 _includes/sidebar/sidebar.html 하나만 만드셔도 됩니다.

사이드바 파일은 각각 아래 구조의 반복입니다.

<div class="sidebar_component">
    {% include sidebar/파일명.html %}
</div>

sidebar_component class를 사용합니다.

참고로 각 sidebar_component 파일은 아래와 같은 구조로 만들 것입니다.

<div class="sidebar_title">각 component 제목</div>

내용

2.8.1. 사이드바 관련 _layouts/default.html

_layouts/default.html의 div id=”main” 부분에 include 태그로 삽입합니다.

<!-- _layouts/default.html의 div id="main" 부분 -->
<div id="main">
    <div id="sidebar1">
        {% include sidebar/sidebar1.html %}
    </div>
    <div id="sidebar2">
        {% include sidebar/sidebar2.html %}
    </div>
            
    <!-- 이후 부분 생략 -->

2.8.2. 사이드바 관련 assets/css/stylesheet.scss

---
---
//...

.sidebar_component{
    border-bottom: 1px solid #cccccc;
    margin: 15px;
}

.sidebar_title {
    display: inline-block;
    text-align: left;
    font-weight: bold;
    height: auto; width: calc(100% - 30px);
    font-size: 16px;
    letter-spacing: -1px;
    padding-bottom: .3em;
}

#hyper a {border: 1px solid #959595; padding: 0 9px; border-radius: 5px; font-size: 16px;}

//...

@media only screen and (min-width: 1600px){    
    //...

    #sidebar1 {
        position: sticky; top: 0; z-index: 10;
        width: 280px; height: 100vh; float: left; padding-right: 15px; background-color: #f4f4f6; border-right: 1px solid #cccccc;
        line-height: 145%;
        overflow: auto; display: block;
    }

    #content {
        width: 940px; min-height: 100vh; padding: 15px 30px 50px 30px; margin: 0 auto 15px auto;
    }

    #sidebar2 {
        position: sticky; top: 0; z-index: 10;
        width: 280px; height: 100vh; float: right; background-color: #f4f4f6; border-left: 1px solid #cccccc;
        line-height: 145%;
        overflow: auto; display: block;

        //...
    }
}

@media only screen and (max-width: 1600px) and (min-width: 1020px){
    //...

    #sidebar1 {
        position: sticky; top: 0; z-index: 10;
        width: 24%; max-width: 280px; height: 100vh; float: left; padding-right: 15px; background-color: #f4f4f6; border-right: 1px solid #cccccc;
        line-height: 145%;
        overflow: auto; display: block;
    }

    #content {
        width: 70%; min-height: 850px; padding: 15px 15px 450px 15px;
        
        @media screen and (max-width: 1600px) and (min-width: 1166px){margin-left: 300px;}
        @media screen and (max-width: 1166px) and (min-width: 1020px){margin-left: 26%;}
    }

    #sidebar2 {
        position: absolute; bottom: 15px;
        float: right; padding-right: 15px; background-color: #f4f4f6; border: 1px solid #cccccc; border-radius: 6px;
        line-height: 145%;
        display: block;

        @media screen and (max-width: 1600px) and (min-width: 1166px){width: calc(100% - 315px); margin-left: 300px;}
        @media screen and (max-width: 1166px) and (min-width: 1020px){width: 70%; margin-left: 26%;}

        //...
    }
}

@media screen and (max-width: 1020px){
    //...

    #content {width: 100%; padding: 0 15px 500px 0; float: left;}

    #sidebar1 {
        position: fixed; top: 45px; z-index: 10; display: none; overflow: auto; background-color: #e9ecef;
        width: 100%; height: calc(100% - 45px); margin: 0 0 0 0; float: left; line-height: 145%;
    }

    #sidebar2 {
        position: absolute; bottom: 15px;
        width: 100%; padding-right: 15px; background-color: #f4f4f6; border-left: 1px solid #cccccc;
        line-height: 145%;
        display: block;

        //...
    }
}

@media (prefers-color-scheme: 'dark') {
    //...
}

[Line 24~46(PC)]
2개의 사이드바 모두 position을 sticky로 했습니다. 따라서 본문 아래쪽을 보고 있어도 사이드바가 위로 올라가지 않습니다. overflow는 auto로 했습니다. 사이드바가 길어져서 화면에 보이지 않으면 사이드바만 따로 스크롤할 수 있습니다.
content를 가운데 정렬하기 위해서 margin: 0 auto 15px auto; 속성을 적용했습니다. margin의 순서는 상우하좌(시계방향)이므로 margin-top: 0; margin-right: auto; margin-bottom: 15px; margin-left: auto;와 같습니다. 좌우 margin이 auto이므로 좌우는 가운데 정렬이 됩니다.(단, 이때 _layouts/default.html에서는 sidebar1, sidebar2, content 순으로 작성해야 함.)

[Line 48~76(태블릿)]
sidebar1은 PC에서와 동일하게 sticky, auto로 합니다.
다만, sidebar2는 PC와 달리 position은 absolute로 합니다. bottom: 15px;을 추가하여 main의 아래쪽에 위치하도록 합니다. overflow는 visible로 하되, 기본값이므로 안 써도 됩니다.
sidebar2를 아래쪽에 위치시키기 위해서 content의 아래쪽 padding을 450px로 크게 잡았습니다.
창 크기에 맞게 width를 조정하도록 했습니다.(media 태그, calc 사용)

[Line 78~96(모바일)]
먼저 sidebar1을 보겠습니다. position은 fixed로 하여 화면에 고정되게 합니다. 그리고 top: 45px; 속성을 추가하여 header 바로 아래 위치하게 합니다. 애드센스 등을 적용하게 되면 애드센스에 묻히지 않도록 z-index: 10; 속성을 추가합니다.(z-index 숫자가 클수록 위로 올라옴.) display: none; 속성을 추가하여 sidebar1이 보이지 않게 합니다(버튼을 누르면 자바스크립트 코드에 의해 display: block;으로 바뀜). overflow는 auto로 합니다. background-color를 #e9ecef로 지정했습니다.
sidebar2와 content는 태블릿과 유사한 방식(absolute, bottom 등을 사용)으로 하되, 수치만 조정합니다.

2.9. 카테고리 기능 구현

2.9.1. 카테고리 관련 _config.yml

# category(config.yml 39~43행)
categories_main: [정보, 프로그래밍, 수성컴의_작품]
categories_information: [Windows, 안드로이드(일반), 안드로이드(앱), 라즈베리파이, 정보_기타]
categories_programming: [VS_Code, Git, 웹개발, C++, Verilog, 프로그래밍_기타]
categories_esd: [절정_및_오피스, 웹사이트_및_웹앱, 작품_기타]

보통 categories 배열 하나를 사용하지만, 저는 카테고리를 계층 구조로 만들기 위해 4가지 배열을 선언했습니다. categories_main에는 정보, 프로그래밍, 수성컴의_작품을 넣었고, 각각 categories_information, categories_programming, categories_esd의 상위 카테고리가 됩니다.

2.9.2. _includes/archive_single.html

{% assign post=include.param %}

{% if post.thumbnail %}
	{% assign thumbnail=post.thumbnail %}
{% else %}
	{% assign thumbnail="/assets/images/sujaimage.png" %}
{% endif %}

<li class="hover">
	<a href="{{post.url}}">
		<div class="listTitle">
			{{post.title}}<span class="date">{{post.date | date: "%Y. %m. %d."}}</span>
		</div>
		<span class="thumbnail">
			<img src="{{thumbnail}}"/>
		</span>
		<span class="summary">
			{{post.description}}
		</span>
	</a>
</li>

홈 화면과 각 카테고리 페이지에서 글 목록을 띄울 때 글 하나를 띄우기 위한 소스 코드입니다.

[Line 1]

{% assign post=include.param %}

post 변수를 선언하고 include.param으로 초기화합니다. archive_single.html을 include할 때 param이라는 이름의 parameter(매개변수)를 지정하면 그 값이 include.param이 됩니다. 글(post) 하나 하나가 param으로 들어올 것입니다. 그러면 post.변수명은 글의 머리말에서 지정한 변수가 됩니다.

[Line 3~7]
글에 thumbnail이 있으면 thumbnail=post.thumbnail로 하고, 글에 thumbnail이 없으면 thumbnail=블로그로고로 합니다.

나머지는 그냥 읽어 보시면 이해하실 수 있을 것입니다.

2.9.3. _layouts/category_page.html

---
layout: default
meta: <!-- <meta name="robots" content="noindex"> 2023. 11. 20. 수정: SEO에 좋지 않은 것 같아서 삭제 -->
---

<h2>{{page.title}}</h2>

{% for post in site.posts %}
    {% include archive_single.html param=post %}
{% endfor %}

{{content}}

[Line 3]

meta: <meta name="robots" content="noindex">

구글 검색 로봇이 수집하지 못하게 하기 위한 메타태그를 meta 변수에 넣었습니다. 이것을 사용하려면 2.9.4절의 내용대로 _layouts/default.html을 수정해야 합니다.
(2023. 11. 20. 수정) SEO에 그닥 좋은 영향을 미치지 않는 것 같아서 삭제했습니다.

[Line 6]

<h2>{{page.title}}</h2>

이 레이아웃을 각 카테고리 페이지가 쓸 것이므로 page.title은 카테고리 이름이 됩니다. 카테고리 이름을 h2 태그로 감쌌습니다.

[Line 8~11 for문]
for문은 반복문입니다.
site.posts는 블로그의 모든 글이 들어 있는 배열입니다.
그러므로 이 반복문에서는 블로그의 모든 글에 대해 그 글을 post 변수에 대입한 뒤 param=post로 하여(2.9.2절에서 언급한 그 param 맞습니다.), archive_single.html을 include합니다.

[Line 13 content]
이건 그 밖에 카테고리별로 쓸 내용이 있으면 들어갈 부분입니다.

2.9.4. 메타태그 관련 _layouts/default.html

_layouts/default.html의 head 태그 그룹에 아래 코드를 넣습니다.

<!-- _layouts/default.html의 head 태그 그룹에 아래 코드를 삽입 -->
{{page.meta}}
{{layout.meta}}

page.meta는 각 페이지(예: 글, 404.html 등)의 머리말에서 meta 변수에 지정한 값입니다.
layout.meta는 각 레이아웃(예: _layouts/category_page.html)의 머리말에서 meta 변수에 지정한 값입니다.
모두 메타태그를 가리킬 변수이므로 head 태그 그룹 안에 넣는 것입니다.(메타태그가 원래 어디에 들어가는지 생각해 보세요.)

2.9.5. 각 카테고리 페이지 파일

프로젝트 root(최상위) directory에 categories 폴더를 만들고 그 안에 각 카테고리 페이지 파일을 만들었습니다. 카테고리 개수가 많으면 많을수록 귀찮으실 것입니다.. 반복 작업이니 조금만 견뎌 보세요.ㅎㅎ 저는 안드로이드(앱) 카테고리(categories/android_app.html)를 예를 들겠습니다.

---
layout: category_page
title: 안드로이드(앱) 카테고리 글 목록
permalink: "category/안드로이드(앱)"
---

다른 카테고리들도 각각 파일을 만들어야 하는데 카테고리 이름과 permalink만 바꾸시면 됩니다.
permalink는 영구주소입니다. 제 블로그의 경우, 블로그 주소가 https://sooseongcom.com이고, 안드로이드(앱) 카테고리의 permalink가 category/안드로이드(앱)이므로 안드로이드(앱) 카테고리의 주소는 https://sooseongcom.com/category/안드로이드(앱)가 됩니다.

2.9.6. _includes/sidebar/category_list.html

이제 사이드바에 카테고리 목록을 띄워 보겠습니다. _includes/sidebar/category_list.html을 만들고 아래와 비슷한 구조로 작성합니다.

<div class="sidebar_title">카테고리</div>

<div class="category">
    <a href="/category/정보">정보</a>
</div>

{% for category in site.categories_information %}
    <div class="category_sub">
        <a href="/category/{{category}}">{{category}}</a>
    </div>
{% endfor %}

<div class="category">
    <a href="/category/프로그래밍">프로그래밍</a>
</div>

{% for category in site.categories_programming %}
    <div class="category_sub">
        <a href="/category/{{category}}">{% include category.html cate=category %}</a>
    </div>
{% endfor %}

<div class="category">
    <a href="/category/수성컴의_작품">수성컴의_작품</a>
</div>

{% for category in site.categories_esd %}
    <div class="category_sub">
        <a href="/category/{{category}}">{{category}}</a>
    </div>
{% endfor %}

상위 카테고리들은 그냥 코드를 써 주되, 각 상위 카테고리 코드 아래에 for문으로 하위 카테고리들을 출력해 줍니다.
상위 카테고리는 div class=”category”로 합니다.
하위 카테고리는 div class=”category_sub”로 합니다.

2.9.7. category list 관련 _includes/sidebar/sidebar1.html

<!-- 앞부분 생략 -->
<div class="sidebar_component">
    {% include sidebar/category_list.html %}
</div>

_includes/sidebar/sidebar1.html에 위 코드블록을 삽입합니다.

2.9.8. category list 관련 assets/css/stylesheet.scss

---
---
//...

.category a{color: #ee55ee;}

.category_sub a{color: #5555ee;}

.category_sub{
    padding-left: 16px;
}

//...

@media only screen and (min-width: 1600px){    
    //...

상위 카테고리의 하이퍼링크 색상(.category a)은 #ee55ee로 합니다.
하위 카테고리의 하이퍼링크 색상(.category a)은 #5555ee로 합니다.
하위 카테고리 왼쪽에는 16px의 padding을 주었습니다.

2.9.9. category list 결과

좌측 사이드바 카테고리 목록
카테고리 목록이 깔끔하게 완성되었습니다.

2.10. 글(post) 작성 방법

글은 post 폴더 안에 작성합니다. 보통 jekyll blog의 글을 쓸 때에는 Markdown이라는 언어를 이용합니다. Markdown 언어 자체를 여기서 설명하지는 않겠습니다. 문법이 간단하므로 따로 검색해서 공부하시기 바랍니다. 참고로 HTML 코드를 그냥 써도 작동하므로, 색상 설정 등 마크다운으로 하기 힘든 것이 있다면 HTML 코드를 쓰시면 됩니다.

각 글의 파일명 및 확장명은 yyyy-mm-dd-title.md의 형태로 작성합니다.(참고로 Markdown 말고 html로 글을 작성할 것이라면 확장명에 html을 써도 됩니다. 그럴 사람들은 잘 없겠지만…)
각 글 파일의 구조는 아래와 같습니다.

---
layout: post
title: " 제목"
description: "안녕하세요. 요약요약요약..."
author: 글쓴이
categories: [상위카테고리, 하위카테고리]
code_block: true
thumbnail: "썸네일 주소"
---

글 내용

[Line 2]
layout: post
layout을 post로 설정합니다.

[Line 3]
title: “글 제목
글 제목은 title 변수에 씁니다.

[Line 4]
description: “안녕하세요. 요약요약요약…
요약을 작성하는 곳입니다.

[Line 5]
author: 글쓴이
글쓴이 이름은 author에 썼습니다. 팀블로그라면 이 변수가 중요하겠죠?

[Line 6]
categories: [상위카테고리, 하위카테고리]
상위 카테고리 이름과 하위 카테고리 이름을 모두 categories 변수에 넣었습니다.

[Line 7]
code_block: true 또는 code_block: false
제 블로그는 개발 블로그이므로 코드블록을 쓸 때가 생깁니다. 코드블록은 자바스크립트를 사용하므로 항상 켜 놓으면 속도 저하가 일어날 가능성이 있다고 생각했습니다. 그래서 code_block 변수를 만들어서 true(사용)와 false(사용 안 함)로 구분하였습니다.

[Line 8]
thumbnail: “썸네일 주소
글 목록, RSS 피드, SNS 등에서 볼 수 있는 썸네일 이미지의 주소를 입력합니다.

[Line 10~]
머리말 아래에는 Markdown 형식으로 글을 작성합니다. Markdown은 완전한 표준이 있는 것은 아니고, 적용되는 누리집마다 약간씩 다른 점이 있습니다. Jekyll에서 특별히 적용되는 점은 아래와 같습니다.

  • Liquid 태그 사용 가능(이건 당연한 건가요?)
  • 하이퍼링크 새 탭으로 열기를 하려면 괄호 뒤에 {: target=”_blank”} 붙이면 됩니다.
    • 예1) 네이버 ←이 하이퍼링크를 만드는 코드는 아래와 같음.
      [네이버](https://naver.com){: target="_blank"}
    • 예2) https://google.com ←이 하이퍼링크를 만드는 코드는 아래와 같음.
      <https://google.com>{: target="_blank"}
  • Liquid 태그 강의를 하는 등 Liquid 태그 코드블록을 작성하고 싶으시면 `와 \` 사이를 raw 태그와 endraw 태그로 감쌉니다.
# permalink for posts(config.yml 36~37행)
permalink: "post/:title"

각 글(post)의 주소는 “블로그주소/post/파일명에쓴제목“이 되도록 설정했습니다.
참고로 :title은 각 글의 파일명에 쓴 제목을 의미합니다.

2.11. 코드블록(highlight.js)

2.11.1. 코드블록 관련 layouts/post.html

코드블록은 highlight.js(코드블록)와 highlightjs-line-numbers.js(줄번호)를 사용했습니다.
highlight.js를 사용하면 Markdown으로 글을 작성할 때 ```로 양쪽을 감싼 내용이 코드블록으로 나타납니다.
2.11.1.1. highlight.js를 사용하기 위해서 layouts/post.html을 수정해야 합니다.

---
layout: default
---

<article>
    <!-- ... -->

    {% if page.code_block %}
        <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/vs2015.min.css">
        <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>
        
        <script>
        hljs.highlightAll();
        hljs.initLineNumbersOnLoad();
        </script>
    {% endif %}

    {{content}}

</article>

<!-- ... -->

8~17행을 보겠습니다.

[Line 8 if문의 시작]
{% if page.code_block %} 2.10절 각각의 글 머리말에서 page.code_block을 true 또는 false로 설정했습니다. 바로 이 if문에서 사용하기 위함입니다. page.code_block==true일 때에만 if문 안에 있는 코드가 번역되어 출력됩니다.

[Line 9~10]
highlight.js 누리집
2.11.1.2. https://highlightjs.org/로 접속합니다.
2.11.1.3. 197 languages and 246 styles를 클릭합니다.

highlight.js demo
2.11.1.4. 좌측 Themes 중에서 원하는 테마의 이름을 알아 둡니다. 저는 VS 2015로 하겠습니다.

2.11.1.5. 다시 https://highlightjs.org/로 돌아가서 Get version x.x.x를 클릭합니다. 스크린샷을 찍을 때에는 11.7.0이 최신버전이었습니다.

Getting highlight.js
2.11.1.6. 여기 나와 있는 코드를 그냥 복사하면 기본 테마가 적용됩니다. 우리가 정해둔 예쁜 테마를 적용하기 위해 styles directory를 클릭합니다.(새탭으로 열기를 추천)

GitHub highlight.js
2.11.1.7. 원하는 테마의 파일명을 확인합니다. 제가 적용할 VS 2015는 vs2015.css이군요. vs2015를 기억해 두겠습니다.

2.11.1.8. 다시 Getting highlight.js 페이지(2.10.1.6절 과정)로 돌아옵니다. 이제 cdnjs, jsdelivr, unpkg, Custom package 중 원하는 방식을 선택하되, default를 방금 확인한 테마 파일명으로 바꾸어 줍니다. 예를 들어 VS 2015를 적용하려면 default를 vs2015로 바꿉니다. 그러면 아래와 같이 됩니다.

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/vs2015.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>

이것이 바로 2.10.1절 도입에서 보여드린 코드블록의 9~10행입니다.

[Line 11~16]
GitHub highlight.js
2.11.1.9. https://github.com/wcoder/highlightjs-line-numbers.js에 접속합니다.
2.11.1.10. CDN은 둘 중 하나를 택하여 11행 부분에 넣습니다.
2.11.1.11. 함수를 실행하는 스크립트 코드를 복사해서 14~15행 부분에 넣습니다.(주의: 13, 16행은 <script>, </script> 코드임.)

2.11.2. 코드블록 관련 stylesheet.scss

줄번호와 관련하여 CSS 수정사항이 있습니다.

---
---
//...

article{
    //...

    /* for block of numbers */
    .hljs-ln-numbers {
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;

        text-align: center;
        color: #ccc;
        border-right: 1px solid #CCC;
        vertical-align: top;
        padding-right: 5px !important;

        /* your custom style here */
    }

    /* for block of code */
    .hljs-ln-code {
        padding-left: 10px !important;
        font-family: "Nanum Gothic Coding", sans-serif;
    }

    //...
}
    
//...

@media only screen and (min-width: 1600px){    
    //...

highlightjs-line-numbers.js GitHub repository의 설명에 나온 스타일 코드를 복사해 주었습니다. 다만, 21행과 28~29행 부분은 제가 수정했습니다.

[Line 21]
padding-right: 5px !important;
!important;를 넣지 않으면 이 속성이 다른 것에 묻혀서 적용되지 않는 문제가 있습니다. 그러므로 !important;를 넣어서 코드블록의 좌측 padding이 다른 속성보다 우선시되도록 합니다.

[Line 28]
Line 21과 동일한 이유로 !important;를 넣습니다.

[Line 29]
font-family: “Nanum Gothic Coding”, sans-serif;
나눔고딕코딩 글꼴을 사용하도록 합니다. 2.4절에서 해당 글꼴을 import 했습니다.

2.12. 이미지 클릭 시 새 탭으로 열기를 위한 _includes/jsscript.html

_includes/jsscript.html 파일을 생성하여 아래와 같이 작성합니다.

<!-- 이미지 클릭 시 새 탭으로 열기 -->
<script type="text/javascript">
    let img = document.querySelectorAll("article img");	//actual
    for (let x = 0; x < img.length; x++) {
        img[x].onclick=function() {
            let win=window.open('');
            win.document.title = '이미지 크게 보기';
            win.document.body.innerHTML='<div id="button"><button onclick="window.close()">이미지 닫기 Close image</button></div>	<div id="imgview"><img src="'+this.src+'" alt="show-img-big"/></div>	<style>#button{width: 100%; height: 5%;} button{width: 100%; height: 100%; font-size: 3vh;} #imgview{width: 100%; height: 95%;} img{width: 100%; height: 100%; object-fit: contain;} </style>'
        }; 
    }
</script>

(2023. 12. 01. var를 let으로 수정하였음.)
article 태그 안에 있는 모든 img(태그? 쿼리?)들을 img 변수에 넣습니다. 사실 모든 img 태그들을 저장하는 ‘img’는 변수는 아닙니다. 언뜻 보면 배열처럼 생겼는데, 실제로는 NodeList 객체라고 합니다.
그 다음 for문을 통해 x=0부터 x<img.length까지 x를 1씩 증가시키며 실행합니다.(img.length: img 객체의 길이. 즉, img 수.)
for문이 실행되면 x를 클릭했을 때 새 탭이 열리며 이미지를 크게 띄우도록 합니다.

2.12.1. 이미지 클릭 시 새 탭으로 열기 관련 _layouts/post.html

_layouts/post.html의 맨 아래에 아래 코드를 추가하였습니다.

{% include jsscript.html %}

2.12.2. 이미지 클릭 시 새 탭으로 열기 관련 assets/css/stylesheet.scss

---
---
//...

article{
    //...

    /* 여기부터 이미지 클릭 시 새 탭 관련 */
    img:hover{
        cursor: zoom-in;
    }
    /* 여기까지 이미지 클릭 시 새 탭 관련 */

    //...
}
    
//...

@media only screen and (min-width: 1600px){    
    //...

글 본문의 이미지에 마우스 커서를 올려 두면 커서가 돋보기 모양으로 바뀌게 했습니다.

2.12.3. 이미지 클릭 시 새 탭으로 열기 결과

커서올림
이미지에 커서를 올리면 커서 모양이 돋보기로 바뀝니다.

이미지 크게 보기 탭
이미지를 클릭하면 이미지를 크게 보실 수 있습니다. 상단의 ‘이미지 닫기 Close image’를 클릭하면 탭이 닫힙니다.

블로그 내 검색 기능을 제공하기 위하여 jekyll-tipue-search를 사용하였습니다. jekyll-tipue-search는 MIT Licence를 따르므로 블로그 테마 소스코드를 공개할 필요가 없으며 수정 및 재배포가 가능합니다.

jekyll-tipue-search-GitHub
https://github.com/jekylltools/jekyll-tipue-search로 접속합니다. Code를 클릭하여 clone을 하든지 ZIP으로 내려받든지 하시면 됩니다.

assets 폴더 tipue
내려받은 파일 중 assets 폴더를 안에 있는 tipuesearch라는 폴더를 여러분의 블로그 테마의 assets 폴더에 넣습니다.
다만, assets/tipuesearch/css/normalize.css는 불필요하므로 삭제합니다.

내려받은 파일 중 assets 폴더 밖에 있는 search.html은 블로그 테마 폴더의 root(최상위)에 넣습니다.

2.13.1. search.html 수정

---
title: Search
description: "Search this site"
layout: page
permalink: /search/
tipue_search_active: true
exclude_from_search: true
meta: <meta name="robots" content="noindex">
---

<div class="searchform">
  <form action="/search">
    <div class="tipue_search_left"><img src="{{ "/assets/tipuesearch/search.png" | relative_url }}" class="tipue_search_icon"></div>
    <div class="tipue_search_right"><input type="text" name="q" id="tipue_search_input" pattern=".{1,}" title="At least 1 characters" required></div>
    <div style="height: 60px;"></div>
    <p>Powered by <a href="https://github.com/jekylltools/jekyll-tipue-search" target="_blank">Tipue Search</a></p>
  </form>
</div>

<div id="tipue_search_content"></div>

<script>
$(document).ready(function() {
  $('#tipue_search_input').tipuesearch({
    'wholeWords': false,
    'showTime': false,
    'minimumLength': 1
  });
});
</script>

[Line 8]
검색 로봇이 search.html을 탐지하지 못하게 합니다.

[Line 11, 18]
Line 12~17을 div class=”searchform”으로 감싸 주었습니다.

[Line 14]
한 글자만 입력해도 검색할 수 있도록 pattern과 title을 수정하였습니다.

[Line 24~28]
검색 옵션을 지정할 수 있는 부분입니다.

  • wholeWords: 영어로만 검색할 것인가?(우리는 한글 검색을 해야 하니 false로 합니다.)
  • showTime: 검색이 완료되기까지 소요된 시간을 표시하는가?
  • minimumLength: 최소 글자수

2.13.2. _includes/sidebar/search.html

<div class="sidebar_title">검색</div>

<div class="searchform">
  <form action="/search">
    <div class="tipue_search_left"><img src="{{ "/assets/tipuesearch/search.png" | relative_url }}" class="tipue_search_icon"></div>
    <div class="tipue_search_right"><input type="text" name="q" id="tipue_search_input" pattern=".{1,}" title="At least 1 characters" required></div>
    <div style="clear: both;"></div>
    <p>Powered by <a href="https://github.com/jekylltools/jekyll-tipue-search" target="_blank">Tipue Search</a></p>
  </form>
</div>

_includes/sidebar/search.html은 search.html에서 searchform 부분을 복사, 수정하여 만들었습니다.

2.13.3. 검색 기능 관련 _layouts/default.html

_layouts/default.html의 head 태그 그룹 안에 아래 소스코드를 넣습니다.

<!-- _layouts/default.html의 head 태그 그룹 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<link rel="stylesheet" href="/assets/tipuesearch/css/tipuesearch.css">
<script src="/assets/tipuesearch/tipuesearch_content.js"></script>
<script src="/assets/tipuesearch/tipuesearch_set.js"></script>
<script src="/assets/tipuesearch/tipuesearch.min.js"></script>

2.13.4. 검색 기능 관련 _includes/sidebar/sidebar1.html

<div class="sidebar_component">
    {% include sidebar/search.html %}
</div>
<!-- 뒷부분 생략 -->

2.13.5. 검색 기능 관련 assets/css/stylesheet.scss

---
---
//...

article{
    //...

    /* 여기부터 검색 상자 */
    .searchform {
        font-size: 14px;

        a{
            color: #000070; text-decoration: underline
        }
    }
    /* 여기까지 검색 상자 */

    //...
}
    
//...

@media only screen and (min-width: 1600px){    
    //...

2.13.6. 검색 기능 관련 _config.yml

내려받은 파일 중에는 _config.yml 파일이 있는데 그 소스코드를 복사하여 여러분 블로그 테마에 있는 _config.yml에 추가(덮어쓰기 아님)하시면 편리합니다. 저는 약간 더 수정했습니다.

# Tipue search settings
tipue_search:
  include:
    pages: false
  exclude:
    files: [search.html]

위의 코드블록 기준으로
4행 pages: false는 layout이 pages인 것을 검색 결과에 포함하지 않겠다는 뜻이고,
5~6행은 search.html을 검색 결과에 포함하지 않겠다는 뜻입니다.

2.14. Pagination(페이지 나누기)

글이 많으면 글 목록이 너무 길어질 것입니다. Pagination이라는 기능을 이용하여 글 목록을 여러 페이지로 나눌 수 있습니다. Jekyll에서는 Pagination 기능이 있는 플러그인을 제공하고 있습니다. 저는 jekyll-paginate-v2를 사용해 보겠습니다. 이전 버전의 jekyll-paginate는 글 전체 목록에서만 페이지를 나눌 수 있고, 카테고리별 페이지 나누기를 할 수는 없었습니다. 이와 달리 jekyll-paginate-v2는 카테고리 페이지까지 각각 페이지 나누기를 할 수 있다는 장점이 있습니다. 다만, GitHub Pages에서는 jekyll-paginate-v2를 지원하지 않으므로 주의하시기 바랍니다.(저는 GitHub 안 쓰고 GitLab 쓸 거라서 괜찮습니다.)

2.14.1. Pagination 관련 _config.yml

# ...

# Build settings(Line 30~34)
theme: 
plugins:
  - jekyll-paginate-v2
  - jekyll-sitemap

# ...

# Pagination(새로 추가)
pagination:
  enabled: true
  per_page: 10
  sort_field: 'date'
  sort_reverse: true
  permalink: "/page/:num/"

[Line 6(2.2절 기준 Line 33)]
plugins에 jekyll-paginate-v2를 추가합니다.

[Line 11~17]
enabled를 true로 해야 pagination이 작동됩니다.
per_page는 각 페이지에 표시할 글의 수입니다.
sort_field는 정렬 기준입니다. 저는 ‘date’로 했습니다.
sort_reverse는 ‘내림차순으로 할 것이냐?’입니다. 저는 true로 했습니다.(최신글이 위로 오게 함.)
permalink는 각 페이지의 주소입니다. 저는 “/page/:num/”로 했습니다. num이 1인 경우에는 생략됩니다. 그러므로 num이 2일 때로 예를 들면, 글목록주소/page/2가 될 것입니다.

2.14.2. Pagination 관련 Gemfile

# ...
# If you have any plugins, put them here!
group :jekyll_plugins do
  gem "jekyll-paginate-v2"
  gem "jekyll-sitemap"
end
# ...

프로젝트 root(최상위)의 Gemfile에서 group :jekyll_plugins do를 찾아 그 아래에 gem “jekyll-paginate-v2”를 추가합니다.

2.14.3. Pagination을 위해 index.markdown → index.html

pagination은 확장명이 html일 때에만 작동합니다. 따라서 index.markdown을 index.html로 바꾸어 줍니다.
그리고 첫 화면에서도 pagination이 작동되게 하기 위해서 머리말을 수정합니다.

---
# Feel free to add content and custom Front Matter to this file.
# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults

layout: home
pagination:
    enabled: true
---

5~6행을 참고하시기 바랍니다.

2.14.4. Pagination 관련 _layouts/home.html와 _layouts/category_page.html

{% for post in paginator.posts %}
    {% include archive_single.html param=post %}
{% endfor %}

_layouts/home.html와 _layouts/category_page.html 모두 site.posts를 paginator.posts로 변경합니다.

아래는 페이지 아래에 위치할 번호 단추들을 만드는 코드입니다. _layouts/home.html와 _layouts/category_page.html 모두 이 코드를 기존 코드 아래에 넣어 줍니다.

<div id="pagination_button_list">
    {% if paginator.previous_page!=nil %}
        <a class="arrow_button" href="{{paginator.previous_page_path}}"></a>
    {% else %}
        <span class="pagination not_button"></span>
    {% endif %}
    
    {% assign start=paginator.page | minus: 1 | divided_by: 10 | times: 10 | plus: 1 %}
    {% assign end=start | plus: 9 %}

    {% if paginator.total_pages < end %}
        {% assign end=paginator.total_pages %}
    {% endif %}

    {% for i in (start..end) %}
        {% if i==1 %}
            {% if paginator.page==1 %}
                <a class="current_page" href="/">1</a>
            {% else %}
                <a class="differ_page" href="/">1</a>
            {% endif %}
        {% else %}
            {% if i==paginator.page %}
                <a class="current_page" href="/page/{{i}}">{{i}}</a>
            {% else %}
                <a class="differ_page" href="/page/{{i}}">{{i}}</a>
            {% endif %}
        {% endif %}
    {% endfor %}

    {% if paginator.next_page!=nil %}
        <a class="arrow_button" href="{{paginator.next_page_path}}"></a>
    {% else %}
        <span class="pagination not_button"></span>
    {% endif %}
</div>

단순한 if문, for문 설명은 생략하고, 먼저 10~11행을 설명 드리겠습니다.
Liquid에서는 계산을 할 때 C언어처럼 y=a+b 따위로 하면 안 됩니다. y=y | plus: 1 같은 형태로 해야 합니다.

  • plus: +(덧셈)
  • minus: -(뺄셈)
  • times: *(곱셈)
  • divided_by: /(나눗셈)
    • 나누는 수(divisor, 除數)가 정수일 경우: 나머지를 버림.
    • 나누는 수(divisor, 除數)가 실수일 경우: 소수의 나눗셈을 함.

[Line 10]

{% assign start=paginator.page | minus: 1 | divided_by: 10 | times: 10 | plus: 1 %}

이 코드는 start=(paginator.page-1)/10*10+1을 계산하는 코드입니다. paginator.page는 현재 페이지 번호입니다.
예를 들어 현재 페이지 번호가 13이면, start=(13-1)/10*10+1=12/10*10+1=1*10+1=11이 됩니다.
처음에 paginator.page에서 1을 빼고 마지막에 다시 1을 더하는 이유는 paginator.page 10으로 나누어떨어지는 수일 경우를 대비하기 위함입니다. 현재 페이지가 10인 경우를 생각해 보세요.

[Line 11]

{% assign end=start | plus: 9 %}

end는 그냥 start에 9를 더한 값으로 했습니다. 예를 들어 start=11이면, end=11+9=20입니다.

[Line 17~31]
1번 페이지 주소에서는 /page/1이 생략된다는 점을 유의하시기 바랍니다.(if문으로 예외처리함.)

◀ 11 12 13 14 15 16 17 18 19 20 ▶
그러면 대략 위와 같은 모습이 될 것입니다.

2.14.5. Pagination 관련 assets/css/stylesheet.scss

---
---
//...

#pagination_button_list{
    display: block;
    margin-top: 15px;
    text-align: center;
    line-height: 2.5;

    a{
        border: 1px solid #333333;
        padding: 3px 5px 2px 5px; margin: 0 15px 0 0;
    }

    .current_page{
        color: #ff00ff;
    }

    .arrow_button{
        color: #0969da;
    }

    .not_button{
        color: #cccccc;
    }
}

//...

@media only screen and (min-width: 1600px){    
    //...

페이지 아래의 단추들의 style을 지정하였습니다.

Pagination-buttons
최종적으로 이런 모습이 됩니다.

2.14.6. Pagination 관련 각 카테고리 html 파일 머리말 수정

각 카테고리 html 파일의 머리말에 아래의 내용을 추가합니다.

pagination:
    enabled: true
    category: 안드로이드(앱)

2.15. 404.html, about.markdown

404.html은 Page not found 오류 페이지(존재하지 않는 주소로 접속하면 여기로 연결됨.)이고, about.markdown은 블로그 소개 글입니다. 여러분의 취향대로 수정하시면 됩니다.

2.16. rss

rss는 확장명 없이 파일명만 ‘rss’로 했습니다. 어떤 사람들은 ‘feed.xml’로 하기도 합니다. rss 파일을 프로젝트 root(최상위) 경로에 둡니다.

---

---

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ site.title | xml_escape }}</title>
    <description>{{ site.description | xml_escape }}</description>
    <link>{{ site.url }}{{ site.baseurl }}/</link>
    <atom:link href="{{ "/rss" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml"/>
    <pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
    <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
    <generator>Jekyll v{{ jekyll.version }}</generator>
    {% for post in site.posts limit:10 %}
      <item>
        <title>{{ post.title | xml_escape }}</title>
        <description>{{ post.content | xml_escape }}</description>
        <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
        <link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
        <guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
        {% for tag in post.tags %}
        <category>{{ tag | xml_escape }}</category>
        {% endfor %}
        {% for cat in post.categories %}
        <category>{{ cat | xml_escape }}</category>
        {% endfor %}
      </item>
    {% endfor %}
  </channel>
</rss>

이 코드를 rss 파일에 넣습니다.

2.17. sitemap 플러그인으로 sitemap.xml 만들기

# ...
# If you have any plugins, put them here!
group :jekyll_plugins do
  gem "jekyll-paginate-v2"
  gem "jekyll-sitemap"
end
# ...

Gemfile에서 group :jekyll_plugins do를 찾아 그 밑에 gem “jekyll-sitemap”을 추가합니다.

2.18. robots.txt

robots.txt는 검색 로봇의 검색 허용 범위를 지정하는 파일입니다. 프로젝트 root(최상위) 경로에 둡니다.

---
---
User-agent: *
Allow:/

위의 코드블록 내용은 모든 검색 로봇이 블로그의 모든 글을 검색하는 것을 허용한다는 뜻입니다. 참고로 네이버 검색 로봇만 따로 지정하려면 User-agent를 Yeti로 하여 밑에 작성하시면 됩니다.

2.19. _includes/og.html

페이스북, 카카오톡 등에 URL을 올리거나 보내면 썸네일과 요약 등이 표시되는 사례를 보신 적이 있을 것입니다. 이것은 바로 Open Graph를 활용한 것입니다. meta 태그를 이용하시면 됩니다.

<!--Open Graph and description s -->
{% if page.title %}
    <meta property="og:title" content="{{page.title}}">
{% else %}
    <meta property="og:title" content="블로그이름">
{% endif %}

{% if page.layout == "post" %}
    <meta property="og:type" content="article">
    <meta property="og.article.author" content="{{page.author}}">   
{% else %}
    <meta property="og:type" content="website">
{% endif %}

{% if page.url == "/index.html" %}
    <meta property="og:url" content="블로그주소">
{% else %}
    <meta property="og:url" content="블로그주소{{page.url}}">
{% endif %}

{% if page.thumbnail %}
    <meta property="og:image" content="{{page.thumbnail}}">
{% else %}
    <meta property="og:image" content="블로그로고주소">
{% endif %}

{% if page.description %}
    <meta property="og:description" content="{{page.description}}">
    <meta name="description" content="{{page.description}}">
{% elsif page.layout==category_page %}
    <meta property="og:description" content="{{page.title}}">
    <meta name="description" content="{{page.title}}">
{% else %}
    <meta property="og:description" content="{{site.description}}">
    <meta name="description" content="{{site.description}}">
{% endif %}
<!--Open Graph and description e -->

이런 내용으로 작성하여 _includes 폴더 안에 og.html로 저장합니다.

2.19.1. Open Graph 관련 _layouts/default.html

<!-- _layouts/default.html의 head 태그 그룹에 아래 코드를 삽입 -->
{% include og.html %}

메타태그이므로 _layouts/default.html의 head 태그 그룹에 위 코드블록의 코드 한 줄을 삽입합니다.

2.20. 글 마무리

제 글을 읽어 주셔서 감사합니다. 제 글에 오류가 있거나 질문 있으시다면 댓글 달아주시면 감사드리겠습니다.

2.21. 참고 자료

1) Uno Kim. 2015. “Hangul test : 지킬(Jekyll)로 깃헙 블로그 만들 때”, Uno’s Blog. (2023. 07. 07. 방문). https://djkeh.github.io/articles/Hangul-test-jekyll-tips-kor/
2) Ari Kim. 2019. “Github Page Jekyll 에 카테고리 추가하기”, Dev Ari. (2023. 07. 07. 방문). https://blog.devari.kr/2019/jekyll/jekyll-category-setting
3) 공부하는 식빵맘. 2021. “[Github 블로그] minimal-mistake 블로그 카테고리 만들기 (+ 전체 글 수)”, 평생 공부 블로그 : Today I Learned‍. (2023. 07. 07. 방문). https://ansohxxn.github.io/blog/category/
4) 천보성. 2018. “jekyll을 이용한 Github 블로그 만들기”, Labs. (2023. 07. 07. 방문). https://labs.brandi.co.kr/2018/05/14/chunbs.html
5) goodGid. 2023. “Liquid 문법 개념과 사용법”, Github. (2023. 07. 07. 방문). https://goodgid.github.io/What-is-Liquid-Grammer/
6) Shopify. n. d. “Liquid”, Liquid template language. (2023. 07. 07. 방문). https://shopify.github.io/liquid/
7) Jekyll. n. d. “Jekyll Docs”, Jekyll. (2023. 07. 07. 방문). https://jekyllrb.com/
8) Jekyll. 2020. “Jekyll Docs(한국어 번역)”, Jekyll. (2023. 07. 07. 방문). https://jekyllrb-ko.github.io/
9) 코곰. 2021. “CSS가 이상하게 적용될 때, user agent stylesheet체크!!”, Connecting the dots. (2023. 07. 07. 방문). https://piaflu.tistory.com/109
10) hang_kem_0531. 2022. “[Web] User Agent Stylesheet”, 행갬로그. (2023. 07. 07. 방문). https://velog.io/@hang_kem_0531/Web-User-Agent-Stylesheet
11) Sammy Baek. 2021. “Liquid란”, ExtraBrain. (2023. 07. 07. 방문). https://seungwubaek.github.io/front-end/liquid/liquid/
12) codesd. n. d. “Can not configure favicon using Jekyll and github pages”, codesd.com. (20##. 07. 07. 방문). https://www.codesd.com/item/can-not-configure-favicon-using-jekyll-and-github-pages.html
13) chy0428. 2021. “yaml/yml 파일에서 참조 변수 사용하기”, ha0.log. (2023. 07. 07. 방문). https://velog.io/@chy0428/yamlyml-%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-%EC%B0%B8%EC%A1%B0-%EB%B3%80%EC%88%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0
14) Yenarue. 2020. “[Jekyll] GitHub 블로그 포스팅들을 연도별로 분류하기”, Yenarue’s Log. (2023. 07. 07. 방문). https://yenarue.github.io/tip/2020/05/01/Jekyll-Yearly-Posts/
15) TheoryDB. 2019. “[Jekyll Blog] Tipue Search를 이용하여 블로그 검색 기능 만들기”, TheoryDB. (2023. 07. 07. 방문). https://theorydb.github.io/envops/2019/05/11/envops-blog-tipue-search
16) Eottabom’s Lab. 2020. “Tipue Search로 블로그 검색 기능 추가하기”, Eottabom’s Lab. (2023. 07. 07. 방문). https://eottabom.github.io/post/tipuesearch-%EA%B2%80%EC%83%89%EA%B8%B0%EB%8A%A5/
17) Harsik. 2020. “깃허브 블로그(GitHub Blog) 만들기 6 - 페이지네이터 구현”, Harsik’s blog. (2023. 07. 07. 방문). https://harsik.github.io/github/2020/01/06/makeGithubBlog6.html
18) PengPengTo. 2017. “Jekyll에서 카테고리 페이지 나누기”, PengPengTo. (2023. 07. 07. 방문). https://pengpengto.gitlab.io/blog/tech/2017/06/08/jekyll-category_pagination.html
19) 박재희. 2023. “지킬 블로그 RSS Feed 설정하기”, JH Blog. (2023. 07. 07. 방문). https://jehuipark.github.io/blog/without-plugin-rss-feed
20) Jekyll. n. d. “Atom/RSS feed”, Jekyll Codex. (2023. 07. 07. 방문). https://jekyllcodex.org/without-plugin/rss-feed/
21) Google. 2023. “noindex로 검색 색인 생성 차단하기”, Google 검색 센터. (2023. 07. 07. 방문). https://developers.google.com/search/docs/crawling-indexing/block-indexing?hl=ko