문제 재발견
- 이전에 Jekyll Chirpy 테마 카테고리 중복/누락 TroubleShooting 글에서
_layouts/categories.htmlLiquid 템플릿을 수정해서 카테고리 문제를 해결했다고 생각지만, 계속해서 버그가 확인됨- 카테고리 목록 페이지(
/categories/)는 제대로 표시됨 - 하지만 개별 카테고리 페이지(
/categories/kubernetes/)에 들어가면 메인 카테고리와 서브 카테고리가 전부 섞여서 표시됨 - 예시:
Certification > Kubernetes(서브카테고리): 1개 포스트Kubernetes > Architecture(메인카테고리): 34개 포스트/categories/kubernetes/접속 시: 35개 포스트 전부 표시
- 카테고리 목록 페이지(
근본 원인
- 이전 해결책은
_layouts/categories.html(목록 페이지)만 고친 것 - 진짜 문제는 Jekyll Archives 플러그인
Jekyll Archives 플러그인의 동작 방식
categories: [Certification, Kubernetes]형태의 포스트가 있으면site.categories['Certification']에도 포함되고site.categories['Kubernetes']에도 포함됨/categories/kubernetes/와 같은 1단계 경로로만 페이지를 생성하고/categories/certification/kubernetes/같이 2단계 이상으로는 페이지를 생성하지 않음
_layouts/category.html의 한계1{% raw %}{% for post in page.posts %}{% endraw %}page.posts는 Jekyll Archives가 이미 생성한 데이터- Liquid 템플릿에서는 이미 섞인 데이터를 받음
- 페이지 생성 자체는 Ruby 플러그인이 하기 때문에 Liquid로는 근본 해결 불가
해결 방법
- 커스텀 Ruby 플러그인을 작성해서 Jekyll Archives를 대체
1. Jekyll Archives의 categories 비활성화
_config.yml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17# 변경 전 jekyll-archives: enabled: [categories, tags] layouts: category: category tag: tag permalinks: tag: /tags/:name/ category: /categories/:name/ # 변경 후 jekyll-archives: enabled: [tags] layouts: tag: tag permalinks: tag: /tags/:name/
2. 카테고리 플러그인 작성
_plugins/hierarchical-categories.rb1 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# frozen_string_literal: true module Jekyll # Generates hierarchical category pages # Primary categories: /categories/primary/ # Secondary categories: /categories/primary/secondary/ class HierarchicalCategoryPage < Page def initialize(site, base, primary, secondary = nil) @site = site @base = base @dir = if secondary File.join('categories', primary.downcase.gsub(' ', '-')) else 'categories' end @name = if secondary "#{secondary.downcase.gsub(' ', '-')}.html" else "#{primary.downcase.gsub(' ', '-')}.html" end self.process(@name) self.read_yaml(File.join(base, '_layouts'), 'category.html') # Set category name for display self.data['title'] = secondary || primary self.data['category_name'] = secondary || primary self.data['primary_category'] = primary self.data['secondary_category'] = secondary # Filter posts based on category hierarchy if secondary # Secondary category: posts where categories[0] == primary AND categories[1] == secondary self.data['posts'] = site.posts.docs.select do |post| post.data['categories'] && post.data['categories'][0] == primary && post.data['categories'][1] == secondary end else # Primary category: posts where categories[0] == primary self.data['posts'] = site.posts.docs.select do |post| post.data['categories'] && post.data['categories'][0] == primary end end end end class HierarchicalCategoryPageGenerator < Generator safe true priority :low def generate(site) return unless site.layouts.key? 'category' # Collect all primary and secondary categories primary_categories = {} site.posts.docs.each do |post| next unless post.data['categories'] categories = post.data['categories'] primary = categories[0] secondary = categories[1] if categories.length > 1 next unless primary primary_categories[primary] ||= Set.new primary_categories[primary] << secondary if secondary end # Generate pages for each primary category primary_categories.each do |primary, secondaries| # Generate primary category page site.pages << HierarchicalCategoryPage.new(site, site.source, primary) # Generate secondary category pages secondaries.each do |secondary| next if secondary.nil? site.pages << HierarchicalCategoryPage.new(site, site.source, primary, secondary) end end end end end핵심 로직:
- 메인 카테고리:
post.categories[0]만 매칭 - 서브 카테고리:
post.categories[0] == primary AND post.categories[1] == secondary동시 매칭 - URL 구조:
- 메인 카테고리:
/categories/kubernetes/ - 서브 카테고리:
/categories/certification/kubernetes/
- 메인 카테고리:
- 메인 카테고리:
3. 카테고리 목록 페이지 링크 수정
_layouts/categories.html- 서브카테고리 URL을
/categories/sub/에서/categories/primary/sub/로 수정 - URL 마지막
/제거 (Jekyll이.html파일을 디렉토리로 인식하는 문제 방지)
- 서브카테고리 URL을
56줄 메인 카테고리 링크
1 2 3 4 5# 변경 전 {% raw %}{% capture _category_url %}/categories/{{ category_name | slugify | url_encode }}/{% endcapture %}{% endraw %} # 변경 후 {% raw %}{% capture _category_url %}/categories/{{ category_name | slugify | url_encode }}{% endcapture %}{% endraw %}121줄 서브 카테고리 링크
1 2 3 4 5# 변경 전 {% raw %}{% capture _sub_ctg_url %}/categories/{{ sub_category | slugify | url_encode }}/{% endcapture %}{% endraw %} # 변경 후 {% raw %}{% capture _sub_ctg_url %}/categories/{{ category_name | slugify | url_encode }}/{{ sub_category | slugify | url_encode }}{% endcapture %}{% endraw %}
결과
- 메인 카테고리 페이지:
/categories/kubernetes/- 메인이 카테고리가 kubernetes인 모든 포스트 표시
- 서브 카테고리 페이지:
/categories/certification/kubernetes/- 메인 카테고리가 Certification, 서브 카테고리가 Kubernetes인 포스트만 표시
- 카테고리 목록 페이지에서 클릭 시 올바른 URL로 이동
- 카테고리 버그 해결!