왜 Hugo인가
정적 사이트 생성기(SSG) 중에서 Hugo를 선택한 이유는 단순하다.
- 빠르다: Go 언어 기반으로 수백 개의 글도 수십 ms 안에 빌드된다
- 배포가 쉽다: GitHub Pages + GitHub Actions로
git push한 번에 자동 배포 - 서버가 없다: DB도, Node.js 서버도 없다. 정적 파일만 호스팅하면 된다
- 무료다: GitHub Pages 무료 플랜으로 충분하다
스택 구성
Hugo (v0.161.1 extended)
└── Stack 테마 (git submodule)
GitHub Pages (호스팅)
GitHub Actions (CI/CD)
Cloudflare (DNS, 커스텀 도메인)
Giscus (댓글, GitHub Discussions 기반)
초기 세팅
1. Hugo 설치 (macOS)
brew install hugo
hugo version
# hugo v0.161.1+extended darwin/arm64
extended 버전이 필수다. SCSS 컴파일에 필요하다.
2. 새 사이트 생성 + Stack 테마 적용
hugo new site my-blog
cd my-blog
git init
git submodule add https://github.com/CaiJimmy/hugo-theme-stack themes/stack
hugo.toml에 테마 등록:
theme = "stack"
3. GitHub 레포 생성 및 배포 설정
<username>.github.io 이름으로 GitHub 레포를 만들고, Settings → Pages에서 GitHub Actions를 소스로 선택한다.
.github/workflows/hugo.yml:
name: Deploy Hugo site to Pages
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.161.1
steps:
- name: Install Hugo CLI
run: |
wget -O hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
sudo dpkg -i hugo.deb
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
- name: Build with Hugo
run: hugo --minify --baseURL "${{ steps.pages.outputs.base_url }}/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./public
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
git push하면 자동으로 빌드되고 배포된다.
커스텀 도메인 연결 (Cloudflare)
Cloudflare를 DNS로 사용하는 경우 설정은 간단하다.
1. CNAME 레코드 추가
| Type | Name | Content | Proxy |
|---|---|---|---|
| CNAME | blog | <username>.github.io | DNS only (회색) |
주의: Proxy 상태(주황 구름)로 두면 GitHub Pages의 HTTPS 인증서 발급이 실패한다. 반드시 DNS only로 설정해야 한다.
2. static/CNAME 파일 생성
blog.yourdomain.com
Hugo 빌드 시 이 파일이 public/ 에 복사되어 GitHub Pages에 전달된다.
3. GitHub 레포 설정
Settings → Pages → Custom domain에 도메인을 입력하면 Enforce HTTPS가 활성화된다.
hugo.toml 주요 설정
baseURL = "https://blog.yourdomain.com/"
locale = "ko-kr"
title = "블로그 제목"
theme = "stack"
paginate = 10
hasCJKLanguage = true # 한국어 단어 수 계산에 필수
[params]
mainSections = ["tech", "til", "log"]
[params.sidebar]
subtitle = "블로그 소개 문구"
avatar = "https://github.com/<username>.png"
[params.article]
toc = true
readingTime = true
[params.colorScheme]
toggle = true
default = "auto"
[params.homepage]
grid = true # 2컬럼 그리드 홈
[params.comments]
enabled = true
provider = "giscus"
콘텐츠 구조
Stack 테마는 content/ 아래 디렉터리가 곧 섹션이 된다.
content/
├── tech/ # 기술 포스트
│ ├── _index.md # 섹션 제목/설명
│ └── 글.md
├── til/ # Today I Learned
├── log/ # 일상 기록
├── archives/ # 아카이브 페이지
└── search.md # 검색 페이지
_index.md frontmatter:
---
title: "Tech"
description: "기술 포스트 모음"
---
커스터마이징
Stack 테마의 파일을 직접 수정하면 테마 업데이트 시 덮어씌워진다. 올바른 방법은 프로젝트 루트의 layouts/에 같은 경로로 복사하는 것이다. Hugo는 프로젝트 layouts/를 테마보다 우선시한다.
예시: 홈 레이아웃 수정
themes/stack/layouts/home.html ← 원본 (건드리지 않는다)
layouts/home.html ← 오버라이드 (여기에 수정)
커스텀 CSS
assets/scss/custom.scss를 생성하면 Stack이 자동으로 포함시켜준다.
/* 색상 테마 오버라이드 */
:root {
--accent-color: #1B365D;
--body-background: #f8f7f2;
}
macOS 스타일 코드 블록
코드 블록 상단에 macOS 신호등 버튼(빨/노/초)을 추가하는 CSS:
.article-content .highlight {
border-radius: 10px;
overflow: hidden;
}
.article-content .highlight:before {
content: "";
display: block;
height: 35px;
background: url("data:image/svg+xml;base64,...") no-repeat 12px center;
background-size: 52px;
}
Giscus 댓글 설정
GitHub Discussions 기반 댓글 시스템이다. 서버가 필요 없다.
1. 준비
- GitHub 레포에서 Discussions 활성화 (Settings → General → Discussions)
- Giscus 앱 설치
2. repoID와 categoryID 조회
GitHub GraphQL API로 ID를 가져온다:
query {
repository(owner: "username", name: "repo-name") {
id
discussionCategories(first: 10) {
nodes { id name }
}
}
}
3. hugo.toml 설정
[params.comments]
enabled = true
provider = "giscus"
[params.comments.giscus]
repo = "username/repo-name"
repoID = "R_..."
category = "Announcements"
categoryID = "DIC_..."
mapping = "title"
lightTheme = "light"
darkTheme = "dark_dimmed"
삽질 모음
세팅하면서 겪은 문제들을 정리했다.
TOML 위젯 형식 오류
# 잘못된 방법 (문자열 배열)
widgets = ["search", "archives"]
# 올바른 방법 (객체 배열)
[[params.widgets.homepage]]
type = "search"
[[params.widgets.homepage]]
type = "archives"
Stack 아이콘 이름
Stack 테마에서 사용할 수 있는 아이콘은 themes/stack/assets/icons/에 있는 SVG 파일명이다. code, pencil 같은 이름은 없다.
사용 가능한 예시: home, archives, tag, hash, search, infinity, brand-github
GitHub Pages 빌드 실패
Error: Unable to locate config file or config directory
git submodule update --init --recursive가 워크플로우에 빠졌을 때 발생한다. actions/checkout@v4의 submodules: recursive 옵션을 꼭 확인하자.
hasCJKLanguage 설정
이 설정이 없으면 한국어 글의 읽기 시간 계산이 정확하지 않다.
hasCJKLanguage = true
완성된 기능
- Hugo + Stack 테마 세팅
- GitHub Actions 자동 배포
- 커스텀 도메인 (Cloudflare DNS)
- Tech / TIL / Log 섹션 구조
- 2컬럼 그리드 홈 레이아웃
- macOS 스타일 코드 블록
- Giscus 댓글
- 좌측 사이드바 검색창
- Archives 페이지 섹션 카드