본 포스트의 주석은 제 생각대로 달았으며, 각 코드의 역할에 대해 제가 생각한대로 표시해둔 것이기 때문에 너무 신뢰하지는 마세요. 이후 개인공부를 통해서 기능에 대해 재해석하더라도 본 포스트에는 반영되지 않고 Minimal-Mistakes 테마의 디렉토리 구조 분석 포스트에 최신화 반영할 예정입니다. Minimal-Mistakes 테마 디렉토리 구조에 대해 공부하고 계시다면 참고하시기 바랍니다.
한창 코드를 수정하고 렌더링을 어느 정도 마친 이후라 이전 사진을 가져와보자면, 블로그 메인 페이지에는 여러 문제점들이 있었다. 우선 사진을 살펴보자.
현재는 읽은 시간이 표시되는 모양이다. 이를 작성일자를 표시하는 방식으로 변경하고 싶다.
각 포스트가 어떤 태그를 담고 있는지 홈 화면에서 한목에 확인할 수 있으면 좋겠다.
포스트로 향하는 링크는 <a> 태그를 쓰고 있기 때문에 밑줄 표시가 되어있다. 그런데 내가 <h2> 태그에 대해서 text-shadow scss 속성을 부여해둔 것이 여기에도 적용이 되기 때문에 밑줄과 함께 엄청나게 겹쳐보인다. 그래서 밑줄을 빼던지 shadow를 빼던지 손을 봐야할 것 같다.
블로그의 메인 페이지는 📁_include📃home.html 에 의해 렌더링된다.
{%- raw -%} --- layout: archive <!-- 오른쪽 여백(margin) 제거하여 넓게 보는 옵션 --> classes: wide --- {{ content }} <h3 class="archive__subtitle">{{ site.data.ui-text[site.locale].recent_posts | default: "Recent Posts" }}</h3> <!-- paginator 가 활성화되어 있다면, post는 paginator.posts 의미, 아니라면 post는 site.posts 의미 --> {% if paginator %} {% assign posts = paginator.posts %} {% else %} {% assign posts = site.posts %} {% endif %} <!-- page.entries_layout를 entries_layout 변수에 저장, 기본 설정은 'list' --> {% assign entries_layout = page.entries_layout | default: 'list' %} <div class="entries-{{ entries_layout }}"> {% for post in posts %} <!-- posts의 각 post마다 archive-single.html 형식으로 추출 --> {% include archive-single.html type=entries_layout %} {% endfor %} </div> <!-- paginator.html 활성화 --> {% include paginator.html %} {% endraw -%}
리스트 형식으로 각 post가 렌더링 되는데, 이때 📃archive-single.html 형식으로 각 포스트들을 추출하게 된다. 때문에 화면의 각 포스트들의 정보를 출력하는 양식을 수정하기 위해서는 📃archive-single.html을 건드릴 필요가 있다.
본격적으로 📃archive-single.html 파일에 대해 분석해보자. 본 파일은 📁_include 폴더 내에 있다.
{%- raw -%} <!-- post.header.teaser가 있다면 teaser는 post.header.teaser, 아니라면 site.teaser--> {% if post.header.teaser %} {% capture teaser %}{{ post.header.teaser }}{% endcapture %} {% else %} {% assign teaser = site.teaser %} {% endif %} <!-- post.id가 있다면 title은 <p> 태그 제거하고 마크다운화, 아니라면 그냥 post.title --> {% if post.id %} {% assign title = post.title | markdownify | remove: "<p>" | remove: "</p>" %} {% else %} {% assign title = post.title %} {% endif %} <!-- class는 include.type, 기본값은 list --> <div class="{{ include.type | default: 'list' }}__item"> <article class="archive__item" itemscope itemtype="https://schema.org/CreativeWork"> <!-- grid가 있고 teaser가 있으면 이미지 티저와 상대경로 표시 / index에는 grid 타입 아니므로 무시 --> {% if include.type == "grid" and teaser %} <div class="archive__item-teaser"> <img src="{{ teaser | relative_url }}" alt=""> </div> {% endif %} <!-- post에 link가 있다면 ~~이렇게 표시, url에 대해 링크 걸음--> <h2 class="archive__item-title no_toc" itemprop="headline"> {% if post.link %} <a href="{{ post.link }}">{{ title }}</a> <a href="{{ post.url | relative_url }}" rel="permalink"><i class="fas fa-link" aria-hidden="true" title="permalink"></i><span class="sr-only">Permalink</span></a> {% else %} <a href="{{ post.url | relative_url }}" rel="permalink">{{ title }}</a> {% endif %} </h2> <!-- 시간을 표시하는 양식을 표시 --> {% include page__meta.html type=include.type %} <!-- post에 description가 있다면 표시 --> {% if post.description %}<p class="archive__item-description" itemprop="description">{{ post.description | markdownify | strip_html | truncate: 160 }}</p>{% endif %} </article> </div> {% endraw%}
우선 눈에 띄는 것은 📃page__meta.html를 include하는 것이다. 눈에 거슬렸던 시간 표시 기능이 여기에 있을 것이다. 이 파일에 대해 살펴보자.
{%- raw -%} {% assign document = post | default: page %} <!-- 모든 것은 문서에 read_time 또는 show_date가 있어야 표시 --> {% if document.read_time or document.show_date %} <p class="page__meta"> <!-- document에 date가 있고 show_date가 활성화되어 있다면 --> {% if document.show_date and document.date %} {% assign date = document.date %} <span class="page__meta-date"> <!-- 달력 이미지를 활성화 --> <i class="far {% if include.type == 'grid' and document.read_time and document.show_date %}fa-fw {% endif %}fa-calendar-alt" aria-hidden="true"></i> <!-- 작성일자 형식 기본값은 "%B %-d, %Y"로 설정하여 date_format에 저장 --> {% assign date_format = site.date_format | default: "%B %-d, %Y" %} <!-- 위에서 저장한 date_format에 맞춰 date 출력한 것을 datetime에 저장 --> <time datetime="{{ date | date_to_xmlschema }}">{{ date | date: date_format }}</time> </span> {% endif %} <!-- document에 read_time이 있고 show_date가 활성화되어 있다면 --> {% if document.read_time and document.show_date %}<span class="page__meta-sep"></span>{% endif %} {% if document.read_time %} <!-- 사이트의 분당 단어 수를 기준으로 words 변수에 값 저장, 중요치 않음 --> {% assign words_per_minute = document.words_per_minute | default: site.words_per_minute | default: 200 %} {% assign words = document.content | strip_html | number_of_words %} <span class="page__meta-readtime"> <!-- 시계 이미지를 활성화 --> <i class="far {% if include.type == 'grid' and document.read_time and document.show_date %}fa-fw {% endif %}fa-clock" aria-hidden="true"></i> <!-- 위에서 저장한 words와 words_per_minute 을 비교함으로써 읽은 시간 정보 출력, 중요치 않음 --> {% if words < words_per_minute %} {{ site.data.ui-text[site.locale].less_than | default: "less than" }} 1 {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }} {% elsif words == words_per_minute %} 1 {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }} {% else %} {{ words | divided_by: words_per_minute }} {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }} {% endif %} </span> {% endif %} </p> {% endif %} {% endraw -%}
자세한 설명은 생략하지만, 페이지를 읽은 시간이나 페이지에 대한 작성 시간 정도를 담고 있는 것으로 보인다. 그리고 옵션에 따라 표시 형식을 달리 한다. 나에게 필요한 것은 readtime이 아니라 date, 즉 작성일자가 중요하므로 그 부분만 집중하면 되겠다.
위에서 우리는 📃page__meta.html에 작성 시간과 읽은 시간에 대한 정보를 표시하는 코드가 있었다. 그렇다면 어떤 코드 때문에 📃home.html 에서는 읽은 시간을 표시하는 것일까. 관련 부분의 코드를 살펴보자.
{%- raw -%} <!-- 시간을 표시하는 양식을 표시 --> {% include page__meta.html type=include.type %} {% endraw -%}
특별히 📃home.html에는 읽은 시간을 표시하라는 양식은 없다. 그렇다면 📃page__meta.html에 읽은 시간을 표시하는 비밀이 숨어있을 것이다.
📃page__meta.html을 봤을 때 로직은 크게 2가지였다.
- document에 date가 있고 show_date가 활성화되어 있다면 시계 이미지를 활성화하고, 읽은 시간을 표시하라.
- document에 read_time이 있고 show_date가 활성화되어 있다면 시계 이미지를 활성화하고, 읽은 시각을 표시하라.
그런데 의문인 점은 내 포스트에는 모두 date를 설정해두었고, show_date가 설정 파일에 의해 활성화가 되어있다면 date가 출력되는 것이 맞다. 그런데 왜 작성 일자가 아닌 수정 시각이 나오는지 알 수 없다. 로직 분석을 확실하게 하기엔 내 실력이 부족하다는 것을 인정하고 📃archive-single.html 파일에서 📃page__meta.html를 끌고 오는 것이 아니라 아예 작성시간을 출력하는 코드를 입력해야겠다.
read_time나 show_date에 관계 없이 그냥 캘린더 아이콘을 활성화하고 post의 date(작성일자)를 출력하는 코드를 출력을 원하는 위치에 작성한다.
{%- raw -%} <!-- 캘린더 모양과 작성일자 표시 --> {% if post.date %} <p class="page__meta"><i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i> {{ post.date | date: "%Y.%m.%d" }}</p> {% endif %} {% endraw -%}
post의 date를 2022.01.07 형식으로 출력하기 위해 | date: "%Y.%m.%d 의 필터 옵션을 부여한다.
그리고 기존에 📃page__meta.html를 include하는 코드를 삭제한다. 아래의 코드이다.
{%- raw -%} <!-- 시간을 표시하는 양식을 표시 --> {% include page__meta.html type=include.type %} {% endraw -%}
시계 모양 아이콘과 읽은 시각이 사라지고, 달력 모양 아이콘과 작성 일자가 잘 출력되었다. 코드를 링크 아래에 배치하여 작성일자가 링크 아래에 위치하도록 했다.
작성일자 옆에 태그를 나열해서 표시하고 싶다. 음 작성일자 아래에 두는 게 나을까. 배치는 고민은 해봐야겠지만 html의 태그를 <span>으로 할지, <p>로 할지의 차이여서 결정은 추후에 해보기로 한다. 아무튼 지금 중요한 것은 태그의 출력이다. 태그를 나열하기 위해서 필요한 코드는 무엇일까.
이것은 카테고리의 소분류 페이지에서 힌트를 얻을 수 있을 것 같다.
현재 커스텀이 덜 된 카테고리 페이지에는 태그가 이런 식으로 출력되고 있다. 그렇다면 이 페이지는 어떤 파일을 통해서 렌더링되고 있을까.
개발자 모드로 나열된 태그를 확인해보면 태그들은 .page__taxonomy라는 클래스명의 <span> 태그의 내에 .page__taxonomy-item-category과 .page__taxonomy-item-tag 라는 클래스명의 <a> 태그로 구성되어 있다. 그렇다면 이 클래스를 VSC에서 전체 찾기(ctrl + shift + 'f')를 통해 이 코드를 출력하는 코드를 📁layout에서 찾아보자.
📁_includes 폴더 내에 존재하는 📃post__taxonomy.html 파일에서 카테고리와 태그를 출력하는 <span> 태그, page__taxonomy를 찾을 수 있었다. 📃post__taxonomy.html 파일의 구조를 살펴보자.
{%- raw -%} <!--Archive page 용-: (post -> page)--> <!--page__taxonomy.html에서 가져 옴--> <!-- site의 layout이 category_archive.type이 있고, post의 카테고리가 1개 이상 있다면 --> {%- if site.category_archive.type and post.categories[0] -%} <!-- site.category_archive.type이 liquid이면 path_type = "#", jekyll-archives이면 path_type = 없음 본 포스트는 liquid이므로 path_type = "#" --> {%- case site.category_archive.type -%} {%- when "liquid" -%} {%- assign path_type = "#" -%} {%- when "jekyll-archives" -%} {%- assign path_type = nil -%} {%- endcase -%} <!-- 위와 동일하고 category가 아닌 태그에 대해 판단 --> {% case site.tag_archive.type %} {% when "liquid" %} {% assign path_type = "#" %} {% when "jekyll-archives" %} {% assign path_type = nil %} {% endcase %} <!-- category_archive.path와 tag_archive.path가 있다면 / 그냥 있다고 생각 --> {%- if site.category_archive.path and site.tag_archive.path -%} <!-- post의 categories를 downcase해서 ','으로 구분해 post_categories에 저장 아마도 리스트 구조로 저장하는 듯, 보통 카테고리는 1개이니까 상관 X --> {%- capture post_categories -%}{%- for category in post.categories -%}{{ category | downcase }}|{{ category }}{%- unless forloop.last -%},{%- endunless -%}{%- endfor -%}{%- endcapture -%} <!-- 위의 카테고리 리스트의 항목을 ',' 기준으로 정렬해서 category_hashes에 저장 --> {%- assign category_hashes = post_categories | split: ',' | sort -%} <!-- categories를 저장한 것처럼 tag들을 저장 --> {% capture post_tags %}{% for tag in post.tags %}{{ tag | downcase }}|{{ tag }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %} <!-- 위의 태그 리스트의 항목을 ','을 기준으로 정렬해서 tag_hashes에 저장 --> {% assign tag_hashes = post_tags | split: ',' | sort %} <!-- 본격적으로 카테고리와 태그를 출력하는 부분--> <span class="page__taxonomy"> <span itemprop="keywords"> <!-- category를 저장한 리스트의 각 항목마다 --> {%- for hash in category_hashes -%} <!-- 각 카테고리를 | 기호로 나누어 keyValue에 저장 --> {%- assign keyValue = hash | split: '|' -%} <!-- keyValue가 단행이 아닌 다행이라면 단행으로 만들어 category_word에 저장 --> {%- capture category_word -%}{{ keyValue[1] | strip_newlines }}{%- endcapture -%} <!-- 1. a태그에 대한 href url을 부여하기 위해 category_word를 아래와 같이 가공 1.1. slugify : 문자열을 소문자 url 형식으로 변환 1.2. prepend: path_type : 1.1 앞에 path_type 표시(#) 1.3. prepend: site.category_archive.path : 1.2 앞에 category_archive.path 표시 1.4. relative_url: 입력값 앞에 baseurl 추가 / 나는 baseurl이 따로 없어서 그냥 url로 적용 2. class 이름은 page__taxonomy-item-category 3. category_word 출력 --> <a href="{{ category_word | slugify | prepend: path_type | prepend: site.category_archive.path | relative_url }}" class="page__taxonomy-item-category" rel="tag">{{ category_word }}</a>{%- unless forloop.last -%}<span class="sep"> </span>{%- endunless -%} {%- endfor -%} <!-- tag를 저장한 리스트의 각 항목마다 적용, 방식은 위의 category와 같다.--> {% for hash in tag_hashes %} {% assign keyValue = hash | split: '|' %} {% capture tag_word %}{{ keyValue[1] | strip_newlines }}{% endcapture %} <a href="{{ tag_word | slugify | prepend: path_type | prepend: site.tag_archive.path | relative_url }}" class="page__taxonomy-item-tag" rel="tag">{{ tag_word }}</a>{% unless forloop.last %}<span class="sep"> </span>{% endunless %} {% endfor %} </span> </span> {%- endif -%} {%- endif -%} {% endraw -%}
그렇다. 정말 복잡한 코드였다. 그렇다면 여기에서 category와 tag를 표현하기 위한 코드를 뽑아서 📃archive-single.html에 붙여넣으면 될 것이다.
일단 단순히 아래의 코드를 집어넣어보자.
{%- raw -%} {%- include post__taxonomy.html -%} {% endraw -%}
디자인은 아직 없지만 내용만큼은 잘 나와준 것 같다. 작성일자 위치를 포스트 제목의 위쪽으로 다시 배치해야 할 것 같다. 그런데 그에 앞서 더 거슬리는 부분이 있다.
나는 보통 태그에 카테고리와 같은 내용을 서두로 먼저 넣었는데, 카테고리를 먼저 출력하고 태그를 출력하기 때문에 중복되는 모습이 보인다. 그래서 카테고리가 없는 📃post__taxonomy2.html를 만들어 적용하려 한다. 어차피 카테고리는 왼쪽 사이드바를 통해 list-up 할 수 있기 때문이다.
category를 출력하지 않고 태그만 출력하는 taxonomy 파일이다. category 부분만 주석처리하거나 아예 삭제하면 되는 간단한 작업이니 코드는 굳이 넣지 않겠다. 이후 📃archive-single.html 코드에 taxonomoy2.html을 include하라고 표시하면 된다.
{%- raw -%} {%- include post__taxonomy2.html -%} {% endraw -%}
카테고리는 출력되지 않고 태그만 출력되도록 잘 반영되었다. 기능적으로는 원하는대로 하지만 디자인적으로 문제가 있다. 이 부분들을 밑에서 개선해보도록 하자.
링크의 위쪽으로 배치한 포스트의 작성일자가 많이 떨어져있는데, 개발자모드로 각 태그들의 클래스를 살펴보면, 제목은 archive__item-title 클래스로 묶여있는데, 이 클래스는 <h2> 태그로, minimal-mistakes 테마의 기본 scss 설정상 h2 태그의 margin이 상당히 크게 되어있기 때문에 이를 오버라이딩해서 덮어쓰거나 아예 <h2> 태그 내에 page__meta(작성일자)를 집어넣는 방법이 있다.
우선 후자를 먼저 해보도록 하겠다.
📃archive-single.html
{%- raw -%} <!-- post에 link가 있다면 ~~이렇게 표시, url에 대해 링크 걸음--> <h2 class="archive__item-title" itemprop="headline" <!-- 캘린더 모양과 작성일자 표시 --> {% if post.date %} <p class="page__meta"><i class="far fa-fw fa-calendar-alt" aria-hidden="true"></i> {{ post.date | date: "%Y.%m.%d" }}</p> {% endif % {% if post.link %} <a href="{{ post.link }}">{{ title }}</a> <a href="{{ post.url | relative_url }}" rel="permalink"><i class="fas fa-link" aria-hidden="true" title="permalink"></i><span class="sr-only">Permalink</span></a> {% else %} <a href="{{ post.url | relative_url }}" rel="permalink">{{ title }}</a> {% endif %} </h2> {% endraw -%}
위의 코드처럼 📃archive-single.html의 캘린더와 작성일자를 표시하는 코드 영역을 <h2> 영역 내로 삽입하였다.
<h2>의 거대한 margin 영역에 영향을 받지 않기 때문에 title을 표시하는 <a> 바로 위쪽으로 위치된 것을 알 수 있다.
이제는 <a>의 특성이었던 text-decoration: underline을 제거할 차례이다. 제거해야 할 밑줄선은 포스트 제목과 태그 리스트인데, 태그들의 경우 page__taxonomy 클래스로 특정 클래스로 지정되어 있고, 그룹화되어 있기 때문에 추후 관련 scss에서 속성을 건들면 된다.
하지만 포스트 제목의 경우 page__meta와 같이 묶여있는 <h2> 태그에 archive__item-title의 클래스명으로 지정되어 있다. 그래서 특별히 포스트 제목의 <a> 태그에 별도의 클래스명을 부여하는 것은 번거로우므로 상위 태그에 대해 살펴보았다.
그런데 상위 태그인 <article>에서 page__taxonomy와 archive__item-title을 모두 포함하는 archive__item 태그가 있음을 알게 되었다. 그렇다면 이 태그에 대한 scss 속성에서 태그 내부의 모든 <a> 태그에 대해 text-decoration: none; 을 부여하면 되겠다.
📁_sass📁minimal-mistakes📃_archive.scss의 .archive__item 영역을 살펴보자.
.archive__item { position: relative; a { position: relative; z-index: 10; } a[rel="permalink"] { position: static; } }
rel의 여부에 따라 position을 달리하는 코드 영역은 무시하면 되고, 우리는 a 태그에 대해 text-decoration: none을 추가로 부여하면 된다. 결과적으로 a 태그는 아래의 코드처럼 보이게 된다.
a { position: relative; z-index: 10; text-decoration: none; }
결과적으로 포스트와 태그에 대한 모든 text-decoration이 none으로 재설정되어 밑줄선이 사라졌다.
페이지에 태그 영역에 대한 디자인을 위해 태그를 관장하는 클래스에 대해 scss 속성을 부여해주어야 한다. 현재 태그는 page__taxonomy-item-tag라는 이름의 클래스로 지정되어 있다.
📃_page.scss 파일에 다음의 코드를 추가해보자.
.page__taxonomy-item-tag { text-decoration: none; margin-right: 0.1em; font-size: $type-size-6; padding: 0.2em 0.6em; background-color: #4a4d4f; border-radius: 3px; border: 1px solid #56595b; color: white; &:visited { text-decoration: none; color: white; } &:hover { text-decoration: none; background-color: #56595b; color: $primary-color; } &:active { text-decoration: none; background-color: $primary-color; color: white; } }
각각의 역할에 대해 설명하겠다.
text-decoration: none;
태그는 더이상 <a> 태그로서의 텍스트 효과를 가지면 안 된다. 그래서 항상 text-decoration을 삭제하는 코드를 넣을 것이다.
margin-right: 0.1em
각 태그들 사이에 여백을 두기 위함이다.
font-size: $type-size-6
태그 글자의 크기가 커서 조금 줄이기 위함이다. 개발자 도구로 보았을 때는 0.8em 내외가 적절했는데, 📃_variables.scss의 type scale에서 보면 6번 사이즈가 0.75em 으로 가장 적절하여 선택했다.
padding: 0.2em 0.6em background-color: #4a4d4f
태그 글자 그 자체가 아니라 영역을 버튼으로 지정하기 위해서 padding과 background-color를 지정했다. padding은 이리저리 값을 조정하면서 적절한 크기를 찾은 것이고, 배경색은 현재 기본 테마 색상보다 조금 더 밝게 조정하여 영역을 가시적으로 구분했다.
border-radius: 3px
태그 영역의 박스의 가장자리를 부드럽게 만들어주는 속성이다. 다른 padding이나 font-size는 em 단위로 한 것과 달리 border-radius는 px 단위로 설정한 이유가 있다.
em은 상대적이고 px는 절대적인데, 상대적인 단위를 border-radius로 두면, 보는 px이나 글자의 길이에 따라 곡률이 제각각이 될 수 있다. 따라서 일정한 곡률을 부여하기 위해 적당한 크기의 px 단위를 설정하였다.
border: 1px solid #56595b
영역의 색만 부여하니 조금 단조로운 느낌이 들어서 거의 티가 나지 않는 조금 더 밝은 회색으로 border를 부여했다. 뜻은 '1px 두께의 밝은 회색 실선을 영역 테두리에 입혀줘라' 라는 뜻이다.
color: white
태그 글자의 색을 white로 설정하였다.
&:visited
<a> 태그를 통해 어떤 태그 archive에 다녀오면, 해당 <a> 태그는 방문 후 링크가 된다. 이때 text-decoration이 별도로 적용될 수 있는데, 이조차 없애기 위해 사용한다. color도 white로 재설정해준다. 사실 위의 코드로만 렌더링했을 때, 방문 후 링크 때문에 별도의 글꼴 색상이 부여되서 추가한 코드이다.
&:hover
같은 클래스에서 마우스를 해당 영역에 올리는 hover를 하는 경우 scss 속성을 다르게 적용하는 것이다. 나는 마우스를 올렸을 때, 배경색은 일부 밝아지고, color가 내 블로그의 메인 색인 노란색으로 적용되었으면 했다.
text-decoration: none; background-color: #56595b; color: $primary-color;
그래서 기존의 배경색보다 조금 밝은 회색을 찾아 넣었고, color는 대분류 카테고리와 같은 색을 사용했다. text-decoration 제거는 항상 깔고 가는 속성이다.
&:active
<a> 태그를 클릭하는 순간에 발생하는 디자인을 관장하는 코드이다. 역시, text-decoration을 제거하고, 배경색을 잠시 강조색으로 바꾸도록 한다.
잘 적용이 되었다.
- 작성일자가 포스트 제목과 너무 붙어있어서 margin 소폭 상향
- 태그라인도 포스트 제목과 너무 붙어있어서 margin 소폭 상향
- 각 포스트 블럭마다도 간격이 너무 작은 듯 해서 list-item에 margin-bottom 부여
