[BlogDev] 사이드바 카테고리 세부분류

작성:    

업데이트:

카테고리:

태그: , , ,

작업 계기

BOJ를 한참 풀다보니, 드는 생각이 있었다. 현재 CODINGTEST 대분류 내에 BOJ가 소분류 카테고리로 들어가 있다.

image

그런데 나는 BOJ 카테고리를 나중에 난이도별로 구분해서 보면 좋겠다고 생각했다. 그러고보니 계속 그런 생각을 해왔다. TIL도 분기별이나 월별로 나눠 정리해보면 좋겠다고 생각했고, PSR도 Volunteer나 Blood Donation 등으로 세부항목을 나누어 구분하면 좋겠다고 생각했다.

사실 nav_list_main과 scss들, 그리고 무엇보다 페이지의 구현 등 디렉토리 구조 자체를 모두 건드리는 작업이라 엄청난 대작업이 될 것임을 느꼈고, 막막해서 건들 수 없었는데, 이제는 미룰 수 없을 것 같다. 포스트가 많아지면 많아질수록 소분류를 위한 추가 작업이 복잡하고 많아질 것이다. 기존 포스트에 카테고리를 추가해야 할 수도 있고 말이다.


작업 계획 및 목표

1. 클릭 시 드롭다운

중분류 항목을 클릭하면 소분류 항목이 밑으로 등장하는 방식을 사용하고 싶다. 이때 hover가 아닌 click 시 드롭다운이 되어야 하는 이유는 mobile이나 tablet 환경에서는 hover가 제한적이기 때문이다.


2. nav_list_main

HTML 구조를 잘 짜야할 것이다. 나중에 스타일링을 어떻게 할 것인지까지 대략적으로 생각해서 넣어야 한다.


3. 📁_pages

breadcrumbs와 categories를 어떻게 해야할지 잘 생각해보자. 현재 중분류 카테고리가 포스트의 categories에서 해당하는 단어가 있는지를 조회하여 필터링해 렌더링해주는데, 이를 그대로 이용하면 소분류마다 페이지를 만들어서 categories를 조회하면 된다.

그러면 기존의 중분류 카테고리를 유지한 상태에서, categories를 리스트 형태로 변환한 뒤, 소분류 카테고리를 넣으면, 카테고리는 포스트에서 2개가 되겠지만, 이를 이용해서 nav_list_main에 해당 categories를 조회할 수 있지 않을까?


4. breadcrumbs

breadcrumbs는 사이트 위의 해당 포스트나 카테고리의 경로를 의미한다.

image

이 사진에서 Home / Categories / Python 이 바로 그것이다. 이것을 만드는 코드는 📁_include📃breadcrumbs.html이다. 미리 살펴본 결과 url의 ‘/’ 표시를 기준으로 항목을 나누어 처리 후 표시하는 듯 하다. 위의 3번에서 permalink에 신경써야 하는 이유이다.


5. 소분류 카테고리 스타일링

디자인 개선은 지정한 class에 대해서 나중에 추가하면 되는 부분이니 논외로 하겠다. 다만 클릭했을 때 display가 none이었던 것이 드러나게 하는 요소가 필요하므로 그 부분까지 고려해서 nav_list_main 의 HTML 코드를 작성하면 되겠다.


포스트 카테고리에 중분류 카테고리 추가

permalink를 위해서는 중분류 카테고리는 두고, 소분류 카테고리를 추가해야 한다. 기존 카테고리가 하나만 들어간 categories를 리스트 형태로 바꿔 소분류 카테고리를 넣으면 어떨까. 먼저 소분류 카테고리를 시험삼아 나눠볼 카테고리로 BOJ 카테고리를 선택했다.

categories를 리스트 형식으로 바꿔 소분류 카테고리를 넣어보았다.


BOJ 테스트 포스트.md

---
title: "[BOJ][🟤0][백준#99999] Sidebar Test Page - Bronze"
excerpt: "Test Page"

categories:
  - [BOJ, Bronze]

tags:
  - [BOJ, ProblemSolving, Python, Bronze]

date: 2022-01-22T12:00
last_modified_at: 2022-01-22T12:00

author_profile: true

toc: true

toc_label: "목차"
toc_icon: "bars"
toc_sticky: true
---

## Test Page

마찬가지로 Silver Test Post도 같은 방식으로 만들었다.


결과 : 실패😥

카테고리를 리스트로 가지는 포스트에 대해 렌더링하는 것 자체에 실패했다. Github에서 Page bulid failure가 발생했다. tags처럼 categories도 여러 개를 가질 때 모두 참조하는 것으로 알고 있는데 이를 다루는 코드에 대해 살펴봐야겠다.


디렉토리의 흐름

📃single.html

먼저 포스트 페이지가 개설되기 위해서는 📃single.html 파일을 살펴보아야한다. 이중 카테고리를 표시하는 코드는 📃category-list.html를 include하면서 생기게 된다. 이 📃category-list.html를 살펴보자.


📃 category-list.html

{% case site.category_archive.type %}
  {% when "liquid" %}
    {% assign path_type = "#" %}
  {% when "jekyll-archives" %}
    {% assign path_type = nil %}
{% endcase %}

{% if site.category_archive.path %}
  {% assign categories_sorted = page.categories | sort_natural %}

  <p class="page__taxonomy">
    <i class="fas fa-fw fa-folder-open" aria-hidden="true"></i> {{ site.data.ui-text[site.locale].categories_label | default: "Categories:" }}
    <span itemprop="keywords">
    {% for category_word in categories_sorted %}
      <a href="{{ category_word | slugify | prepend: path_type | prepend: site.category_archive.path | relative_url }}" class="page__taxonomy-item-tag" rel="tag">{{ category_word }}</a>{% unless forloop.last %}<span class="sep">, </span>{% endunless %}
    {% endfor %}
    </span>
  </p>
{% endif %}


위의 코드를 통해 알 수 있는 것이 있다.


카테고리는 오름차순으로 정렬된다.

{% assign categories_sorted = page.categories | sort_natural %}

위의 코드를 통해 page.categories를 오름차순으로 정렬한 것을 categories_sorted 변수에 저장한다는 것을 알 수 있다. 이 변수를 활용해 이후의 과정을 거친다.


categories에는 리스트가 들어갈 수 있다.

{% for category_word in categories_sorted %}
  <a href="{{ category_word | slugify | prepend: path_type | prepend: site.category_archive.path | relative_url }}" class="page__taxonomy-item-tag" rel="tag">{{ category_word }}</a>{% unless forloop.last %}<span class="sep">, </span>{% endunless %}
{% endfor %}

위의 코드를 보면, 위에서 정렬한 categories_sorted 변수의 각 category_word 마다 <a> 태그의 링크를 만들며 버튼을 생성하고 있다. 그렇다는 것은 categories 자체에 리스트가 들어가는 것은 구조적으로 문제가 되지 않는다는 것이다.


우선 카테고리 리스트 문제가 해결된다면 중분류 > 소분류 카테고리를 순서대로 표시해야 하므로, 정렬은 지양해야 한다. 때문에 📃category-list2.html을 따로 만들어 정렬하지 않는 문서를 만들어 필요한 곳에 include 할 것이다.


렌더링 실패의 이유는?

위의 📃category-list.html 문서에서도 보았듯이 카테고리를 리스트 형식으로 작성하는 것 자체는 문제가 되지 않는다. 그렇다면 왜 렌더링이 실패하는 것일까?


아래는 📃_config.yml 파일의 일부이다.

---
# Outputting
permalink: /:categories/:title/
# paginate: 5 # amount of posts to show
# paginate_path: /page:num/
timezone: America/New_York # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

---
#   permalinks:
#     category: /categories/:name/
#     tag: /tags/:name/

📃_config.yml 파일은 jekyll 엔진의 설정 파일인데 여기에서조차 categories의 하위 categories에 대한 permalink나 방법이 전혀 없다. 이는 카테고리 아래에 하위 카테고리를 넣을 것까지 생각하지는 않았을 수 있다.


대체 방법의 모색

어쩌면 jekyll 엔진 자체의 구조적인 문제일 수도 있다. 아직까지 jekyll 엔진이나 liquid 언어 자체의 깊은 이해가 부족하여 내가 구조를 짤 높은 수준까지는 못 되는 것 같다. 엔진 구조 자체를 이해해야 하는데 이는 디렉토리 구조처럼 파일을 쳐다보며 익힐 수 있는 영역이 아니니까 말이다.

그럼 정석은 아니더라도 어찌됐건 기능은 만들어보려고 한다. 그 방법은 디렉토리 구조를 대 > 중 에다가 > 소 를 추가하려는 지금의 방식 아닌, 대 > 소 로 categories를 설정하고 분류 카테고리는 태그 페이지를 통하는 것이다. 사실상 중분류 카테고리를 종합적으로 볼 일이 많지 않기 때문에 이 방법이 합리적일 수도 있다. 다만 기존 게시물의 categories를 모두 수정해야 하기 때문에 조금 번거롭긴 할 것이다.


작업 계획

  1. 📁_pages의 page관련 md파일을 모두 세부 카테고리에 대한 것으로 바꾼다.
  2. 테스트 포스트 파일을 제작한다. BOJ 카테고리에 대해 진행할 것이다.
  3. 📃nav_list_main 파일을 소분류 카테고리에 대해 수정한다.


📁_pages

이 작업을 위해서 가장 먼저 해야할 일은 page마다 있는 md 파일을 현재 중분류 카테고리에서 소분류 카테고리용으로 작성하는 일이다.

기존 BOJ 카테고리를 구성했던 페이지인 📃category-BOj.md의 코드를 살펴보자.


📃category-BOJ.md

---
title: "BAEKJOON Online Judge"
layout: archive
permalink: categories/BOJ
author_profile: true
sidebar_main: true
---

{% assign posts = site.categories.BOJ %}
{% for post in posts %} {% include archive-single2.html type=page.entries_layout %} {% endfor %}

이 중분류 카테고리를 소분류 카테고리로 바꿔보겠다. 예시로는 Bronze에 대한 내용으로 바꾸겠다.


📃category-BOJ_Bronze.md

---
title: "BOJ[🟤] Bronze"
layout: archive
permalink: categories/boj_bronze
author_profile: true
sidebar_main: true
---

{% assign posts = site.categories.['BOJ Bronze'] %}
{% for post in posts %} {% include archive-single2.html type=page.entries_layout %} {% endfor %}

위에서 조정한 방식대로 Silver에 대한 페이지 코드도 만들었다.


테스트 포스트 파일 제작

📃 2022-01-22_TD_test.md 의 임시 파일을 만들었다. 위에서 pages를 건드렸을 때 적용되도록 폼을 만들었다.

---
title: "[BOJ][🟤0][백준#test] Test Post"

categories:
  - [BOJ Bronze]

tags:
  - [BOJ, ProblemSolving, Python, Bronze]

date: 2022-01-22T12:00
last_modified_at: 2022-01-22T12:00

author_profile: true

toc: true

toc_label: "목차"
toc_icon: "bars"
toc_sticky: true
---

Test Post

마찬가지로 Silver도 같은 방식으로 진행했다.


그리고 이것이 사이드바에서 드러나려면 nav_list_main에서 적절하게 코드를 짜주어야 한다.

html의 <details>, <summary> 태그를 활용하여 각 중분류 카테고리를 클릭할 때마다 소분류 카테고리가 접고 펼쳐지는 방식으로 진행할 것이다.

그런데 편집을 시작하기 전에 앞서 드는 생각은 소분류 카테고리를 다 넣고 나면 📃nav_list_main 파일이 너무 크고 무거워질 것 같다는 생각이었다. 그래서 📁nav-lists 폴더를 따로 만들고 그 안에 각 대분류 카테고리들에 대한 html을 나눠서 include 해보자.


각 대분류별로 html 파일을 만들어 해당 html 코드를 떼어내어 이동시켰다.

image

이를 통해 📃nav_list_main 파일 자체의 코드 길이는 획기적으로 줄어들 수 있었다.

<!--전체 글 수를 세기 위한 연산. sum 변수에 전체 글 수 저장-->

{% assign sum = site.posts | size %}

<nav class="nav__list">
    <input id="ac-toc" name="accordion-toc" type="checkbox" />
    <label for="ac-toc">{{ site.data.ui-text[site.locale].menu_label }}</label>
    <ul class="nav__items" id="category_tag_menu">


        <!--전체 글 수-->
        <li>
            <div>📃 전체 게시글 수 {{sum}} 개</div>
        </li>

        <!-- 대분류 카테고리 include 리스트-->
        <li>
            {% include nav_list_1_frontend.html %}
            {% include nav_list_2_backend.html %}
            {% include nav_list_3_cs.html %}
            {% include nav_list_4_codingtest.html %}
            {% include nav_list_5_etc.html %}
            {% include nav_list_6_private.html %}
        </li>
    </ul>
</nav>


이제 본격적으로 <details> 태그와 <summary> 태그를 활용해 소분류 카테고리를 넣어보자.


우선 현재 해당 파일의 코드 상태이다.

<!-- 대분류 with span 태그-->
<span class="nav__sub-title"> <!-- CodingTest 문자 표시 -->
  CodingTest
</span>

  <!-- 중분류 with ul 태그-->
  <ul class="nav__sub2-title"><!--Coding Test Study 카테고리 글들을 모아둔 페이지인 /categories/coding-test-study 주소의 글로 링크 연결-->
      {% for category in site.categories %}
          {% if category[0] == "Coding Test Study" %}
              <li><a href="/categories/coding-test-study" class="">Coding Test Study ({{category[1].size}})</a></li>
          {% endif %}
      {% endfor %}
  </ul>

  <ul class="nav__sub2-title"><!--BAEKJOON Online Judge 카테고리 글들을 모아둔 페이지인 /categories/BOJ 주소의 글로 링크 연결-->
      {% for category in site.categories %}
          {% if category[0] == "BOJ" %}
              <li><a href="/categories/BOJ" class="">BOJ ({{category[1].size}})</a></li>
          {% endif %}
      {% endfor %}
  </ul>


그리고 이를 아래와 같이 바꾸었다.

<!-- 대분류 with span 태그-->
<span class="nav__sub-title"> <!-- CodingTest 문자 표시 -->
  CodingTest
</span>
    <details>
        <!-- 접힌 상태에서 중분류 -->
        <summary class="nav__sub2-title"> BOJ </summary>

        <!-- 소분류 1. Bronze -->
        <ul class="nav__sub3-title">
            {% for category in site.categories %}
                {% if category[0] == "BOJ Bronze" %}
                    <li><a href="/categories/boj_bronze" class="">[🟤] Bronze ({{category[1].size}})</a></li>
                {% endif %}
            {% endfor %}
        </ul>

        <!-- 소분류 2. Silver -->
        <ul class="nav__sub3-title">
            {% for category in site.categories %}
                {% if category[0] == "BOJ Silver" %}
                    <li><a href="/categories/boj_silver" class="">[⚪] Silver ({{category[1].size}})</a></li>
                {% endif %}
            {% endfor %}
        </ul>
    </details>

  <!-- 중분류 with ul 태그-->
  <ul class="nav__sub2-title"><!--Coding Test Study 카테고리 글들을 모아둔 페이지인 /categories/coding-test-study 주소의 글로 링크 연결-->
      {% for category in site.categories %}
          {% if category[0] == "Coding Test Study" %}
              <li><a href="/categories/coding-test-study" class="">Coding Test Study ({{category[1].size}})</a></li>
          {% endif %}
      {% endfor %}
  </ul>

BOJ가 Coding Test Study 보다 먼저 나오게 하고 싶어서 순서를 이동했고, 각각의 ul 태그들을 details 내의 summary 태그 아래에 병렬적으로 두었다. 중분류 태그인 summary 태그에 nav__sub2-title 클래스를 부여했고, 그 하위인 소분류 카테고리 ul태그에 nav__sub3-title 클래스를 부여했다.


결과 화면

image

image

왼쪽 사이드에 BOJ를 보면, 클릭하기 전에는 형태로 BOJ를 가리키고 있다가, 클릭하면 형태로 되며 하위 리스트가 나온다. scss 속성만 부여하면 되기 때문에 기대했던대로 성공적이다.


디자인

디자인을 어느정도 손 볼 때가 된 것 같다. 우선 위에서도 볼 수 있듯이 중분류 카테고리, 즉 nav__sub2-title의 크기가 크고 옆에 방향표는 없으면 좋겠다.

/* 대분류 카테고리명 */
.nav__sub-title {
  display: block;
  margin: 1.5rem 0 0.3rem 0;
  padding: 0.25rem 0;
  font-family: $sans-serif-narrow;
  font-size: $type-size-5;
  font-weight: bold;
  color: $primary-color;
  text-transform: uppercase;
  border-bottom: 1px solid $border-color;
}

/* summary 아닌 중분류 카테고리 */
.nav__sub2-title {
  font-size: 0.9em;
  margin: 0.2em 0;

  &:hover {
    border-left: 0.2em solid $primary-color;
    padding-left: 0.3em;
  }

  &:active {
    border-color: white;
    color: white;
  }
}

/* summary 중분류 카테고리 */
.nav__sub2_1-title {
  font-size: 0.7em;
  margin: 0.2em 0;

  &:hover {
    border-left: 0.2em solid $primary-color;
    padding-left: 0.3em;
  }

  &:active {
    border-color: white;
    color: white;
  }
}

/* summary 화살표 삼각형 제거 */
.nav__sub2_1-title::-webkit-details-marker {
  display: none;
}

details summary::-webkit-details-marker {
  display: none;
}

/* 소분류 감싸는 div */
.inner_detail {
  border-left: 1px solid $text-color;
  margin-left: 0.2em;
}

/* 소분류 카테고리명 */
.nav__sub3-title {
  font-size: 0.8em;
  margin: 0.1em 0 0.1em 0.5em;

  &:hover {
    border-left: 0.15em solid $primary-color;
    padding-left: 0.3em;
  }

  &:active {
    border-color: white;
    color: white;
  }
}

summary와 li는 같은 0.8em의 font-size여도 화면에서 보이는 크기가 달라서 클래스를 나누어 scss 속성을 별도로 설정했다. 물론 nav_list_4_codingtest.md 파일의 html 코드도 수정했다. 이후 조금씩 조정할 예정이다.


마무리

이렇게 일단은 정석은 아니지만 세부 카테고리를 나눈 사이드바를 만들어 보았다. 하면서 하루종일 붙어 분석했는데 디자인적인 부분도 그렇고 명쾌하게 해냈다는 느낌이 조금 아쉽다. 조금씩 더 손을 봐야겠다. 그 과정까지 본 포스트에 담기에는 거창한 것이 아니어서 거창하거나 기록할 가치가 있는 작업이라면 이후 포스트에 기록하도록 하겠다.

댓글남기기