๐Ÿ“˜ [GithubPages] Jekyll hydejack Search bar ๊ตฌํ˜„ - 4

๐Ÿ“˜ [GithubPages] Jekyll hydejack Search bar ๊ตฌํ˜„ - 4

[GithubPages] Jekyll hydejack Search bar ๊ตฌํ˜„


๋ธ”๋กœ๊ทธ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ธฐ๋Šฅ๋“ค์„ ๊ตฌํ˜„ํ•ด๋ณด๋ฉด์„œ ์žฌ๋ฏธ๋ฅผ ๋ถ™์ด๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ์•ž์œผ๋กœ study๋‚˜ dev๊ธฐ๋ก๋“ค์„ ํฌ์ŠคํŒ… ํ•  ์˜ˆ์ •์ด๋‹ค. ๊ธฐ๋ก๋“ค์ด ๋Š˜์–ด๋‚œ๋‹ค๋ฉด ๋‚ด๊ฐ€ ์ ์—ˆ๋˜ ๊ธ€๋“ค์„ ์‰ฝ๊ฒŒ ์ฐพ์•„๋ณด๊ธฐ ํž˜๋“ค๊ฒƒ ๊ฐ™์•„์„œ Search bar ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด์ž ํ•˜๋Š” ์ƒ๊ฐ์— ์ด ๊ธ€์„ ์ž‘์„ฑํ•œ๋‹ค. ๊ตฌ๊ธ€์—์„œ ๊ฒ€์ƒ‰ํ•˜๋‹ค๊ฐ€ ๋ฐœ๊ฒฌํ•œ SimpleJekyllSearch ์˜คํ”ˆ ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ–ˆ๋‹ค.

โœ… SimpleJekyllSearch ๊ตฌํ˜„


# file: `assets/js/search.json`

---
layout: none
---
[
  {% for post in site.posts %}
    {
		"title"    : "{{ post.title | escape }}",
	    "categories": "{{ post.categories | join: ' >> ' }}",
	    "tags"     : "{{ post.tags | join: ', ' }}",
	    "url": "{{ post.url | prepend: site.baseurl }}",
	    "date": "{{ post.date | date: '%Y๋…„ %m์›” %d์ผ' }}"
    } {% unless forloop.last %},{% endunless %}
  {% endfor %}
]

์ด ํŒŒ์ผ์€ ๊ฒ€์ƒ‰์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๊ฒ€์ƒ‰ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ format์œผ๋กœ ํ‘œํ˜„๋˜๋ฉฐ ์›ํ•˜๋Š” ํ‘œํ˜„ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค.

์œ„ ๊ฒฝ๋กœ์— ์„ธํŒ…ํ•ด์ค€๋‹ค.

2. _includes/body/menu.html ์ƒ๋‹จ ๋ฉ”๋‰ด search bar์ถ”๊ฐ€


# file: `_includes/body/menu.html`

<!-- CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.1/css/all.min.css" />
<div id="_navbar" class="navbar fixed-top">
  <div class="content">
    <span class="sr-only">{{ site.data.strings.jump_to | default:"Jump to" }}{{ site.data.strings.colon | default:":" }}</span>
    <div class="nav-btn-bar">
      <a id="_menu" class="nav-btn no-hover" href="#_drawer--opened">
        <span class="sr-only">{{ site.data.strings.navigation | default:"Navigation" }}</span>
        <span class="icon-menu"></span>
      </a>
      <div class="nav-span">
        <a href="{{ '/search' | prepend: site.baseurl }}" class="nav-btn no-hover top-menu">
          <i class="fas fa-fw fa-search"></i>
          <!-- <span>Search</span> -->
        </a>
      </div>
    </div>
  </div>
</div>
<hr class="sr-only" hidden />

์ƒ๋‹จ ๋ฉ”๋‰ด์— ๋‹๋ณด๊ธฐ ๋ชจ์–‘์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

3. _layout/search.html ๋ ˆ์ด์•„์›ƒ ์ƒ์„ฑ


# file: `_layout/search.html`

---
layout: default
title: Search
permalink: /search/
---
<div class="search-page">
  <div class="search-header">
    <i class="fas fa-search fa-fw search-icon"></i>
    <input id="search-input" type="search" placeholder="Search" />
  </div>
  <ul id="results-container" class="search-results"></ul>
</div>

<ul id="results-container"></ul>

<script src="{{ '/assets/js/simple-jekyll-search.min.js' | relative_url }}"></script>
<script src="{{ '/assets/js/search-init.js' | relative_url }}"></script>
<script>
  document.addEventListener('DOMContentLoaded', initSimpleSearch);
  document.addEventListener('hy-push-state-load', initSimpleSearch);
  initSimpleSearch();
</script>

[!NOTE] /search ํŽ˜์ด์ง€ ์ด๋™์ค‘ template ํŒŒ์‹ฑ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•จ. Hydejack ํ…Œ๋งˆ์—์„œ๋Š” ํŽ˜์ด์ง€ ๋กœ๋”ฉ์—†์ด ์ด๋™ํ•˜๋ฏ€๋กœ search.html์—์„œ ์ง์ ‘ script๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด push-state๋กœ ๋กœ๋”ฉ๋  ๋•Œ js๊ฐ€ ํŒŒ์‹ฑ๋˜์ง€ ์•Š๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋“ฏ ํ•˜๋‹ค. ๋”ฐ๋ผ์„œ js(search-init.js์ƒ์„ฑ)๋Š” ๋ณ„๋„๋กœ ๋ถ„๋ฆฌํ•˜๊ณ  DOMContentLoaded ๋ฐ hy-push-state-load ์ด๋ฒคํŠธ๋ฅผ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผ ํ•œ๋‹ค.


4. search-init.js ์Šคํฌ๋ฆฝํŠธ ์ƒ์„ฑ


# file: _assets/js/search-init.js

function initSimpleSearch() {
	const input = document.getElementById('search-input');
	const results = document.getElementById('results-container');
	if (!input || !results) return;

	if (window.simpleJekyllSearchInstance){
		// ์ด์ „ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ฑฐ (๋™์ผํ•œ DOM์— ๋‘ ๋ฒˆ ์ดˆ๊ธฐํ™” ๋ฐฉ์ง€)
		delete window.simpleJekyllSearchInstance;
	} 
    
    SimpleJekyllSearch({
        searchInput: document.getElementById('search-input'),
        resultsContainer: document.getElementById('results-container'),
        json: '/search.json', // ๋˜๋Š” '{{ "/search.json" | relative_url }}'
        searchResultTemplate: `
        <li class="content-item">
          <div class="content-row">
            <i class="fas fa-folder fa-fw"></i>
            <a href="{url}">{categories}</a>
          </div>
          <div class="content-row">
            <i class="fas fa-book fa-fw"></i>
            <a href="{url}">{title}</a>
          </div>
          <div class="content-row">
            <i class="fas fa-tags fa-fw"></i>
            <a href="{url}">{tags}</a>
          </div>
          <div class="content-row">
            <i class="fas fa-calendar-alt fa-fw"></i>
            <a href="{url}">{date}</a>
          </div>
        </li>
      `,
        noResultsText: '๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.',
        limit: 10,
        fuzzy: false
    });
}
  
  • searchInput : input ํƒœ๊ทธ์— text๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š” ์š”์†Œ
  • resultsContainer : ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ๋ Œ๋”๋ง๋˜์–ด์•ผ ํ•˜๋Š” ์š”์†Œ
  • json : ๊ฒ€์ƒ‰ ๋ฐ์ดํ„ฐ๊ฐ€ json์— ์ง์ ‘ ์ „๋‹ฌ๋œ๋‹ค.
  • searchResultTemplate : ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํ…œํ”Œ๋ฆฟ
  • templateMiddleware : ํ…œํ”Œ๋ฆฟ์—์„œ ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ์ด ๋ฐœ๊ฒฌ๋  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜
  • noResultsText : ์ผ์น˜ํ•˜๋Š” ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ํ‘œ์‹œ
  • limit : ๊ฒŒ์‹œ๋ฌผ ์ˆ˜ ์ œํ•œ
  • fuzzy : ๋œ ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ๋„ ๊ฒ€์ƒ‰ ์ €๋Š” false๋ฅผ ์คฌ์Šต๋‹ˆ๋‹ค.
  • exclude : ๊ฒ€์ƒ‰ ์ œ์™ธํ•ญ๋ชฉ ์ถ”๊ฐ€

5. _sass/my-style.css _sass/_variables.scss

๊ธฐ๋ณธ ๊ฒ€์ƒ‰ ๋ ˆ์ด์•„์›ƒ ๋””์ž์ธ์ด ์ข‹์ง€์•Š์•„์„œ ๐Ÿคฃ ๋ณ„๋„๋กœ css๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

# file: `_sass/my-style.css`
.search-page {
    max-width: 768px;
    margin: 3rem auto;
    padding: 2rem;
    backdrop-filter: blur(8px);
    background: var(--glass-bg);
    border-radius: 16px;
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
}

.search-header {
    display: flex;
    align-items: center;
    background-color: var(--card-bg);
    padding: 0.8rem 1rem;
    border-radius: 12px;
    border: 1px solid var(--border);
    margin-bottom: 2rem;
    transition: border 0.3s ease;
}

.search-header:focus-within {
    border-color: var(--accent);
}

.search-icon {
    color: var(--icon-color);
    font-size: 1.2rem;
    margin-right: 0.8rem;
}

#search-input {
    flex: 1;
    border: none;
    font-size: 1.1rem;
    background: transparent;
    color: var(--text);
    outline: none;
}

.search-results {
    list-style: none;
    padding: 0;
    margin: 0;
    color: var(--text);
}

.search-results li {
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    margin-bottom: 1rem;
    padding: 1rem;
    transition: transform 0.2s ease, background 0.3s ease;
    color: var(--text); // ๐Ÿ‘ˆ ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€
}

.search-results li.no-results {
    color: var(--text);
    font-style: italic;
    opacity: 0.8; 
}

.search-results li:hover {
    background-color: var(--hover-bg);
    transform: translateY(-2px);
}

.search-results a {
    color: var(--link);
    text-decoration: none;
    font-weight: 600; 
}
# file: `_sass/_variables.css`
:root {
    --glass-bg: rgba(255, 255, 255, 0.8);
    --card-bg: #ffffff;
    --border: #ddd;
    --hover-bg: #f0f0f0;
    --text: #111;
    --link: #007acc;
    --icon-color: #666;
    --accent: #007acc;
}

[data-theme="dark"] {
    --glass-bg: rgba(30, 30, 30, 0.5);
    --card-bg: #2a2a2a;
    --border: #444;
    --hover-bg: #3a3a3a;
    --text: #ddd;
    --link: #66ccff;
    --icon-color: #aaa;
    --accent: #66ccff; 
}

hydejack ํ…Œ๋งˆ๋Š” dark mode, light mode ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ‰์ƒ ๋ชจ๋“œ์— ๋”ฐ๋ผ css๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ์ ์šฉ๋˜๊ฒŒ ์ถ”๊ฐ€ํ•œ๋‹ค.

6. search.md ์ƒ์„ฑ


  • _pages ํด๋” ์•ˆ์— ์ƒ์„ฑ
  • ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์ƒ์„ฑํ•˜๋ฉด ์ž๋™์ธ์‹ ๋˜์ง€๋งŒ _pages ํด๋” ์•ˆ์— ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์‹ถ์œผ๋ฉด
  • _config.yml ์—์„œ collections์— pages ์ถ”๊ฐ€
# file: '_config.yml'
collections:
  pages:
    output: true
    permalink: /:name/
# file: `_pages/search.md` 
---
layout: search
title: Search
permalink: /search/
---

search.md ์ƒ์„ฑํ•˜์—ฌ search.html ๋ ˆ์ด์•„์›ƒ์— ์—ฐ๊ฒฐํ•œ๋‹ค.

Search ๊ธฐ๋Šฅ์ด ์ž˜ ์ž‘๋™๋˜๋Š”์ง€ ํ™•์ธ๐Ÿค”


๐Ÿ“‘ Reference



Pagination


ยฉ 2025. All rights reserved.

Powered by Hydejack v9.2.1