이 블로그는 정적 사이트 생성기를 사용하여 웹페이지를 생성하고, 이를 GitHub에 올려서 hosting하고 있습니다. 그 동안은 Jekyll 을 사용하여 페이지를 생성했는데, 이번에 Hugo로 바꿔봤습니다. 어떻게 바꿨는지, 무엇이 좋았는지를 정리해 봤습니다.

 

Why?

Jekyll을 사용한 건 가장 유명한 정적 사이트 생성기이고 GitHub 에서 빌드를 해 주기 때문이었습니다. 적당한 theme 을 찾아 받고 그 위에 글을 올리고, 가끔 약간의 customize를 했습니다.

근데 사용하기가 조금 불편했습니다. 웹 지식이 부족해서인 것 같긴 하지만, 어떤 것이 생성 결과물인지, 내가 customize 하고자 하는 부분과 관련된 코드는 어디에 있는지 등을 찾기 어려웠습니다.

기존 theme의 git repo를 fork 해서 사용하는 것도 별로였습니다. Theme repo 의 최신 변경점을 내 repo 에 반영하기도, 내 변경점과 분리 관리하기도 어려운 구조였어요.

그래서 대안을 찾다 요즘 많이 보이는 Hugo를 사용해 봤습니다. 점점 인기가 많아져 Jekyll 보다 GitHub star 수가 많다는 Hugo는 빠른 것이 강점인 Go 기반의 정적 사이트 생성기 입니다. 일단 마음에 드는 theme 이 있어서 다운받아 본 건데요, 설치하고 잠깐 사용해 보는데 꽤 만족스러워서 바로 옮겼습니다.

   

Migration

Jekyll에서 Hugo로 옮겨가는 과정은 다음과 같습니다.

설치, theme 다운로드 등 기본 사용법에 대한 내용은 공식 홈페이지를 참고해 주세요. Hugo 설치하고, hugo new site 'folder-name' 명령어를 사용해 새 블로그를 만들고, theme 을 theme 폴더에 git submodule로 추가하고 셋업하면, 바로 빌드하고 결과를 확인할 수 있습니다.

이미 Jekyll 블로그를 가지고 있는 경우라면, 다음과 같이 import jekyll 명령어를 사용하여 간편하게 옮길 수 있습니다. huijeong-kim.github.io/ 가 이전에 사용하던 Jekyll 폴더고, migrateHugo를 사용한 새 블로그의 폴더명 입니다. migrate 폴더는 이 명령어를 통해 생성됩니다.

$ hugo import jekyll huijeong-kim.github.io/ migrate

 

저는 처음 Hugo 설치하고 구경하다 글도 옮겨봤는데 잘 되어 그대로 전부 옮겨서, 하나 하나 손으로 옮겼습니다. 그러다 뒤 늦게 이 명령어를 알고 실행해 봤는데 아주 잘 되네요! 다들 이거 쓰세여…

 

Troubleshooting

이전 과정에서 본 아주 소소한(troubleshooting이란 이름을 붙이기도 애매할 정도의) 오류 혹은 이슈들은 다음과 같습니다.

Markdown meta 정보 포맷 오류

제 블로그에선 tags 항목에서 오류가 있었습니다. 기존 블로그를 Hugo로 import 한 뒤 빌드하면 다음과 같은 에러 메시지가 나왔습니다. tags 항목을 iterate 하지 못 하고 있었습니다.

Error: error building site: render: failed to render pages: render of "page" failed: 
"/Users/huijeongkim/Workspace/blog-test/migrate/themes/papermod/layouts/_default/baseof.html:5:8":
execute of template failed: template: _default/single.html:5:8: 
executing "_default/single.html" at <partial "head.html" .>: 
error calling partial: "/Users/huijeongkim/Workspace/blog-test/migrate/themes/papermod/layouts/partials/head.html:19:31": 
execute of template failed: template: partials/head.html:19:31: 
executing "partials/head.html" at <.Params.tags>: range can't iterate over as, rust, type casting

 

사실 이전에는 다음과 같은 형태로 tags 항목을 작성했는데요.

---
date: "2023-05-02T00:00:00Z"
tags: rust, as, type casting
title: as operator in Rust
---

 

Hugo(혹은 제가 사용하는 theme) 에서는 이런 형태로 작성해야 했습니다.

---
date: "2023-05-02T00:00:00Z"
tags: ["rust", "as", "type casting"]
title: as operator in Rust
---

 

이전 블로그에서는 인터넷 어딘가에서 발견한 코드를 복붙해서 조금 이상한 형태였던 것 같긴 해요. 이게 Hugo(혹은 제가 사용한 theme)에서 tags 가져 가는 방식과 다른 것 같고요. 아무튼, 이런 식의 변환 오류가 생길 수 있고, 이 경우 손수 혹은 스크립트 작성해서 변환해야 할 수 있습니다.

 

Post permalink

Jekyll을 사용할 때 블로그 글의 permalink를 아래와 같이 설정했었습니다. 그래서 글 주소는 https://huijeong-kim.github.io/2023/05/02/rust-as-operator/ 과 같은 형태가 되었어요.

permalink: /:year/:month/:day/:title/

 

Hugo로 import 한 뒤에는 글 주소가 https://huijeong-kim.github.io/post/2023-05-02-rust-as-operator/ 로 바뀌었습니다. 달라진 것은 1)post 가 추가 됨, 2) 날짜 형태 입니다.

 

먼저, post가 추가된 이유를 보면,

Hugo의 폴더 구조는 다음과 같고, 모든 컨텐츠들은 content 폴더에 추가됩니다. 그리고 공식 사이트 설명에 따르면 content 폴더 내의 top-level 폴더는 “content section"을 의미한다고 해요. Content section은 post와 같은 폴더로 하위 글을 갖고 있는 section일 수도 있고, archives.md 파일과 같은 단일 페이지로 이루어진 section일 수도 있습니다.

Section 지정 없이 새로운 글을 추가한다면, 글 목록이 아닌 메뉴에 항목이 추가될 것 입니다. hugo new 2023/06/15/my-new-page.md로 글을 추가하려 하면, 블로그 글이 추가되는 것이 아니라 2023이란 context section이 추가되는 것 이죠.

 

그리고 날짜 형태를 보겠습니다. 만일 yyyy/mm/dd 형태의 글을 다음과 같이 추가한다면,

1
hugo new post/2023/05/02/rust-as-operator.md

그럼 post/2023/05/02/rust-as-operator.md 파일이 생성됩니다. 즉, content/post 폴더 안에, 2023 폴더, 그 안에 05 폴더, 그 안에 02 폴더, 그 안에 rust-as-operator.md 파일이 생성됩니다.

yyyy/mm/dd/title 형태의 url을 가져가려면 이런 식의 날짜 hierarchy 를 가질 수 밖에 없더라고요. 공식 사이트 에도 이런 구조가 date-base hierarchy 로 소개되어 있습니다.

 

Content 추가 시 title을 2023/06/15/my-new-page.md로 할 순 없지만, 또 다른 방법이 있더라고요! Title은 2023-06-15-my-new-page.md 등으로 설정하고, md 파일에 url을 지정하면 됩니다.

url 항목을 추가한다면 무사히 이전 링크를 그대로 사용할 수 있습니다. 모든 makrdown 파일을 수정하는 게 좀 귀찮은 일이 될 수 있겠지만, 글 url 수정을 원치 않다면 이렇게 할 수 밖에 없을 것 같습니다. 아래에 설명 될 utterance 댓글 연동 관점에서도 url 유지하는 게 좋기도 하니, 고려해 볼만 합니다.

*2023이라는 section이 추가되고, 동일한 이름의 파일이 이 section에 추가된다면 (2023/06/15/my-new-page.md) 약간의 혼란이 있는 것 같긴 합니다만, 그렇게 쓸 일이 없겠죠.

---
date: "2023-05-02T00:00:00Z"
tags: rust, as, type casting
title: as operator in Rust
url: '/2023/05/02/rust-as-operator-rust/'
---

 

보통 하루에 글 한 개 미만인 저에게는 date-based hierarchy가 딱히 필요하지 않고, title과 link 가 다른 것도 마음에 들지 않아, 그냥 title을 yyyy-mm-dd-title 형태로 모두 바꿨습니다. 사실 이전에 yyyy/mm/dd 형태를 쓴게 후회되네요. 글이 몇 개 안 되어서 다행이었어요.

   

utterance 댓글 재 연동

HugoDisqus 연동을 지원합니다. 하지만 저는 기존 블로그에서 사용했던 utterance를 사용하고, 이전에 달린 댓글을 그대로 유지하고 싶어서 다음과 같이 수정하였습니다.

먼저 theme 에 정의된 comments.html 을 오버라이딩 하는 파일을 추가하였습니다. themes/papermod/layouts/partials/comments.html 에 comment 관련 코드가 있는데, layouts/partials/comments.html 파일을 추가하면 theme 파일을 오버라이딩 할 수 있습니다.

기존 블로그에 삽입했던 utterance script를 나의 comments.html 파일에 붙여넣으면 됩니다. 필요하다면 layouts/_default/single.html 파일을 오버라이딩 하여 comment, navigator, share button간 순서 및 위치 조정을 할 수도 있습니다.

 

저는 utterance의 Blog Post <-> Issue Mapping 옵션을 “Issue title contains page pathname” 옵션으로 사용했습니다. 그 말은 즉, 생성 된 issue들의 이름과 pathname이 같다면 댓글이 연동된다는 의미였습니다.

기존 글들의 pathname을 모두 바꿨기 때문에, utterance로 인해 생긴 issue들의 title을 2023/05/02/rust-as-operator 에서 post/2023-05-02-rust-as-operator로 바꾸니 기존의 댓글들이 새 블로그에서도 정상적으로 보였습니다.

   

Deploy

Jekyll을 사용할 때는 따로 빌드하지 않아도, markdown 글만 커밋해도 github가 빌드해 줬습니다. 이게 Jekyll의 가장 큰 장점이었던 것 같은데, 이제는 이 부분을 다른 방식으로 해결해야 합니다.

많은 사람들이 netlify를 활용하던데요. 저는 가끔 수정되는 정적 사이트를 배포 툴을 사용할 필요가 있을까라는 생각, 내 블로그 URL을 *.netlify.app 로 바꾸고 싶지 않다는 생각에 도입하진 않았습니다.

대신 제 블로그 repo 인 huijeong-kim.github.io 에 생성 결과된 HTML를 업로드하도록 했습니다. Hugo repo의 결과물이 나오는 폴더인 public 폴더를 제 블로그 repo가 되도록 git submodule로 연결하였습니다. 이 아이디어는 검색하다 여기서 보고 따라해 봤어요. (정말 좋은 아이디어에요. 감사합니다!)

< 디렉터리 구조와 연결된 git submodule >

blog
  ├── archetypes
  ├── content
  ├── hugo.toml
  ├── layouts
  ├── public   ----> (submodule) huijeong-kim.github.io
  ├── resources
  └── themes
       └── papermod ---> (submodule) hugo-PaperMod

 

여기서 두 개의 git repo를 관리하는 것이 조금 귀찮아 지는데요. 위의 링크에 소개된 것과 같이 쉘 스크립트로 자동화 해도 되고, git hook을 걸어서 markdown 파일 commit/push 하면 submodule에도 관련 변경점이 같이 commit/push 되도록 관리해도 좋을 것 같습니다.

아직은 git commit이 귀찮지 않은데, 조만간 ChatGPT가 작성해 준 아래의 post-commit hook과 push script를 도입, 가능하다면 GitHub Actions에도 추가해 보면 좋을 것 같아요.

 

post-commit hook을 통한 sub-module commit 자동화

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

# Get the commit message from the initial commit
commit_message=$(git log --format=%B -n 1 HEAD)

# Path to the submodule directory
submodule_dir="path/to/submodule"

# Check if the submodule has any changes
cd "$submodule_dir"
has_changes=$(git status --porcelain)

# Commit the changes in the submodule, if any
if [[ -n "$has_changes" ]]; then
  git add .
  git commit -m "$commit_message (submodule update)"
fi

exit 0

 

Remote commit push 할 때 submodule도 함께 push하는 스크립트

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash

# Path to the submodule directory
submodule_dir="path/to/submodule"

# Remote name for the submodule
submodule_remote="origin"

# Check if the current branch is the branch you want to track
current_branch=$(git rev-parse --abbrev-ref HEAD)
tracked_branch="main"  # Replace with your desired branch name

if [[ "$current_branch" != "$tracked_branch" ]]; then
  exit 0
fi

# Push changes to the main repository remote
git push

# Push changes to the submodule remote
cd "$submodule_dir"
git push "$submodule_remote" "$current_branch"

exit 0

   

좋은 점

빠르다

Hugo는 “빠른 정적 사이트 생성기"로 유명합니다. 처음에는 블로그 글 쓰는 게 자주 있는 것도 아니고, 이 생성 과정이 빠른 것이 크게 의미 있지 않다고 생각했어요. 그리고 빨라 봤자 큰 차이 없게찌.. 라는 생각도 있었고요.

근데 막상 사용해 보니 신세계입니다. Jekyll 사용할 때는 조금 느린 것 같아 markdown 문서를 작성한 후 마지막에 퇴고시에만 bundle exec jekyll serve --watch로 결과 확인하면서 마무리 했습니다. 근데 이젠 글 작성 하면서 Ctrl+S 누를 때 마다 바로바로 빠르게 업데이트 된 웹 페이지를 볼 수 있어 매우X10000 편합니다. 블로그 작성 효율이 올라가고 만족도도 올라가, 블로그에 글을 올리는 것이 좀 더 재밌는 일이 되었습니다.

 

직관적인 구조, 좋은 공식 문서

어디서 부터 어디까지가 theme 인지, output이 어디로 나오는지, 등등이 직관적으로 구성된 단순한 폴더 구조로 보여집니다. 웹을 모르는 저에게는 이 점이 크게 다가왔습니다. 게다가 공식 문서에 궁금한 대부분의 것들이 적혀 있어서, 추후 customize 하고 공부할 때 많은 도움이 될 것 같아요.

 

사용하기 쉬운 툴

hugo 명령어만 있음 어디든 갈 수 있을 것만 같아요. 단순해서 좋아요.

 

손쉬운 테마 도입 및 변경

테마 도입이 매우 쉽고 간편합니다. themes 폴더 아래 git submodule을 추가, hugo.toml 파일 내에 theme = "papermod" 를 추가하면 테마 도입 끝! (config 파일도 yml/toml/json 중 원하는 형태 선택 가능한 것도 또 장점) Theme 을 변경할 때도 새로운 submodule을 추가하고 toml 파일만 변경하면 되어서 매우 편합니다. 아래에서 언급할 overriding 된 파일 관리는 좀 필요하겠지만요.

 

Theme Overriding

제일 좋았던 점 입니다. Theme 코드들을 직접 수정/변경/삭제 하는 것이 아니라 overriding을 할 수 있습니다!!!!!! Static file, Template file 등을 원하는 파일로 변경할 때 overriding 할 수 있습니다. 간단히 themes/my-theme/{변경하고자 하는파일}의 파일의 수정 버전을 {변경하고자 하는 파일}에 두면 됩니다. 즉, themes/my-theme/layouts/partials/comments.html을 수정하고 싶으면 layouts/partials/comments.html 파일을 생성, 원하는 내용을 넣으면 됩니다.

   

그 결과 대 만족!

그 결과 만족스러운 블로그를 얻었습니다. 처음 사용해 보지만 아주 쉽게 소소한 기능을 추가/커스터마이즈도 할 수 있었습니다. 깔끔한 사용성, 직관적인 구조, 디테일한 문서를 보고 있으니 rust 처음 사용할 때 기분이 드네요.

앞으로 어떻게 더 활용할 수 있을지 궁금한데, 더 공부하고 블로그도 멋지게 꾸며 봐야겠어요!