개요
GitHub Actions에서 Hugo 사이트를 빌드·배포할 때, 레이아웃에서 Resize "… webp"나 Fill "… webp"를 사용하면 매 실행마다 콘텐츠·커버 이미지가 WebP로 다시 변환된다. 이미지가 많을수록 빌드 시간이 길어지고, runner는 매번 새 환경이라 이전 빌드의 캐시를 활용하지 못한다. 이 글에서는 Hugo의 resources 캐시와 HUGO_CACHEDIR을 GitHub Actions cache로 저장·복원해, 변경된 소스만 다시 처리하도록 개선한 방법을 정리한다.
대상 독자: Hugo 정적 사이트를 GitHub Actions(또는 GitHub Pages)로 배포하는 개발자, 빌드 시간 단축에 관심 있는 DevOps·블로거.
핵심 요약: actions/cache로 ./resources와 .hugo_cache를 캐시하고, 캐시 키를 content/**, layouts/**, config/**, assets/** 기준 해시로 두면, 입력이 바뀌지 않은 실행에서는 캐시 히트로 빌드 시간이 크게 줄어든다. 실제 적용 커밋은 e703f33에서 diff로 확인할 수 있다.
문제: 매번 끝도 없이 도는 WebP 변환
Hugo는 이미지 리소스를 resources/_gen(기본 resourceDir/_gen)에 캐시한다. 한 번 변환한 결과는 같은 빌드 안에서뿐 아니라, 다음 빌드에서도 같은 경로에 캐시가 있으면 재사용한다. 그런데 CI 환경에서는 다음이 문제가 된다.
- 워크플로가 끝날 때마다 runner가 정리되므로
resources디렉터리가 사라진다. HUGO_CACHEDIR를runner.temp로 두면, 그 경로도 runner와 함께 날아간다.
그래서 두 번째, 세 번째 푸시부터도 “첫 빌드”처럼 모든 이미지를 다시 WebP로 변환하게 되고, 빌드 시간이 계속 길게 나온다. 다른 Hugo 사이트에서는 이 방식으로 캐시를 도입한 뒤 빌드 시간이 7초대에서 약 450ms 수준으로 줄어든 사례가 보고된 바 있다.
해결 전략: actions/cache로 resources와 .hugo_cache 복원
해결책은 캐시할 경로를 워크스페이스 안에 두고, actions/cache로 그 경로를 저장·복원하는 것이다.
- 첫 실행: 캐시 없음 → 전체 빌드 → job 끝에
resources와.hugo_cache가 캐시로 저장된다. - 이후 실행: 캐시 복원 → Hugo가 기존
resources/_gen과 캐시 디렉터리를 보고 변경된 이미지만 다시 처리한다.
캐시 키 전략
캐시는 입력(콘텐츠·레이아웃·설정)이 바뀔 때만 갱신되면 된다. 따라서 키에 hashFiles()로 다음 디렉터리를 넣었다.
content/**layouts/**config/**assets/**
이 중 하나라도 수정되면 새 키가 되어 새 캐시가 저장되고, 아무것도 바꾸지 않으면 이전 캐시가 그대로 복원된다. restore-keys에 hugo-resources-${{ runner.os }}-처럼 접두사만 두어, 정확한 키가 없어도 최근 캐시를 쓸 수 있게 했다.
구현: deploy.yml에 넣은 내용
Checkout 직후, Hugo/Node 설치 전에 Restore Hugo resources cache 단계를 넣었다.
| |
그리고 Build with Hugo 단계에서 HUGO_CACHEDIR를 runner 임시 디렉터리가 아니라 워크스페이스 안으로 바꿨다.
| |
효과는 다음과 같다.
- resources: Hugo가 이미지 등 에셋 파이프라인 결과를 쓰는
resources/_gen이 워크스페이스에 생기고, 이 전체를 캐시 대상으로 둔다. - .hugo_cache: 모듈·기타 파일 캐시를 워크스페이스의
.hugo_cache에 두고, 역시 캐시에 포함해 두 번째 실행부터는 다운로드·처리를 줄인다.
.hugo_cache는 로컬에서 생성돼도 커밋되지 않도록 .gitignore에 추가해 두는 것이 좋다.
위 변경을 한 번에 반영한 커밋은 아래와 같다.
- chore: Update .gitignore to include .hugo_cache and modify deploy workflow to cache Hugo resources
.gitignore:.hugo_cache한 줄 추가..github/workflows/deploy.yml: Checkout 직후Restore Hugo resources cache단계 추가(path:./resources,.hugo_cache/ key:hashFiles('content/**', 'layouts/**', 'config/**', 'assets/**')/restore-keys),Build with Hugo의HUGO_CACHEDIR를${{ github.workspace }}/.hugo_cache로 변경.
흐름 정리: 캐시 적용 전·후
캐시를 쓰기 전과 후의 차이는 아래 다이어그램과 같다.
flowchart LR
subgraph beforeCache["캐시 적용 전"]
A1[Checkout] --> A2[Hugo build]
A2 --> A3["모든 이미지 WebP 변환"]
A3 --> A4[Upload artifact]
end
subgraph afterCache["캐시 적용 후"]
B1[Checkout] --> B2[Restore resources cache]
B2 --> B3[Hugo build]
B3 --> B4["변경분만 변환, 대부분 캐시 사용"]
B4 --> B5[Upload artifact]
B5 --> B6["Cache save if new key"]
end
- 캐시 적용 전: 매번 Checkout → Hugo 빌드 → 전체 이미지 변환 → 아티팩트 업로드.
- 캐시 적용 후: Checkout → 캐시 복원 → Hugo 빌드(대부분 캐시 사용) → 아티팩트 업로드 → 필요 시 새 키로 캐시 저장.
actions/cache는 job 종료 시 같은 키가 없을 때만 자동으로 저장하므로, 별도 save 단계는 넣지 않았다.
대안: repo에 캐시를 커밋하는 방식
캐시를 GitHub Actions가 아니라 repo 안에 두고 싶다면, resources(또는 resources/_gen)를 .gitignore에서 빼고, 로컬이나 별도 CI에서 한 번 빌드한 뒤 그 디렉터리를 커밋하는 방법도 있다. 그러면 Actions cache 용량·만료와 무관하게 항상 같은 캐시가 repo에 있게 된다. 대신 repo 용량이 늘고, 이미지·레이아웃·설정이 바뀔 때마다 그 캐시를 다시 빌드해 커밋해야 하며, 머지 시 충돌 가능성도 있다. 일반적으로는 Actions cache만으로 충분하고, “캐시를 반드시 repo에 두고 싶을 때”만 repo 커밋 방식을 고려하면 된다.
요약
- GitHub Actions에서 Hugo 빌드 시 WebP 변환 시간이 길어지는 이유는, runner가 매번 새로 올라와
resources와HUGO_CACHEDIR가 비어 있기 때문이다. - actions/cache로
./resources와.hugo_cache를 저장·복원하고, 캐시 키를content/**,layouts/**,config/**,assets/**기준 해시로 두면, 입력이 안 바뀐 실행에서는 캐시 히트로 빌드가 크게 짧아진다. HUGO_CACHEDIR를${{ github.workspace }}/.hugo_cache로 두고 이 경로도 캐시에 넣으면, 이미지뿐 아니라 모듈·기타 캐시까지 재사용해 빌드 시간을 더 줄일 수 있다.
이 구성을 적용한 뒤부터는 푸시할 때마다 전체 WebP 변환이 반복되지 않고, 변경된 부분만 처리되므로 GitHub Actions 수행 시간이 눈에 띄게 짧아진다.
참고 문헌
- Hugo — Configure file caches — Hugo 공식 문서, cacheDir·caches 설정.
- Hugo — Image processing — 이미지 처리·캐싱·
--gc설명. - actions/cache — GitHub Actions 캐시 액션 공식 저장소.
- 42jerrykim.github.io — chore: Update .gitignore and deploy workflow to cache Hugo resources — 본문에서 적용한 실제 커밋 diff.
![Featured image of post [DevOps] GitHub Actions Hugo 빌드: WebP 캐시로 빌드 시간 단축](/post/2026-02-25-github-actions-hugo-webp-cache-build-time/wordcloud_hu_58c2e94b14ad7681.webp)
![[Hardware] LattePanda Alpha에 Ubuntu 16.04 LTS 설치 가이드](/post/2018-12-06-install-ubuntu-16.04-on-lattepanda/wordcloud_hu_fc536f8de2cbd4bf.webp)
![[Tutorial] Learn Prompting - 프롬프트 엔지니어링 무료 가이드 정리](/post/2022-12-30-learn-prompting/wordcloud_hu_6a9d105de4834753.webp)
![[Rust] Comprehensive Rust 무료 강의 정리 및 코스 구조](/post/2022-12-30-comprehensive-rust/wordcloud_hu_d1420ff38434cdb6.webp)
![[.NET] 런타임별 Finalizer 호출 차이와 IDisposable 권장](/post/2021-04-27-distructor-called-by-runtime/wordcloud_hu_7b7dd809a5d4bdc3.webp)
![[RPM] Spec 파일에서 주석과 매크로 동시 사용 시 주의사항](/post/2021-11-24-rpm-spec-comments/wordcloud_hu_6d09ac09623081c7.webp)