#dev 수정: 2026-11-05

GitHub Pages 정적 사이트 배포 정리: gh-pages 교체 방식, pip 캐시, requirements 통합

Python 정적 사이트 생성기를 GitHub Actions로 gh-pages에 배포할 때 매번 전체 교체가 정상인지, force_orphan과 pip 캐시, requirements.txt 통합은 언제 적용하면 좋은지 DevBJ 설정으로 정리했습니다.

DevBJ는 content/의 Markdown을 Python 빌더가 docs/로 만들고, 이 폴더를 GitHub Actions가 gh-pages 브랜치에 올리는 구조다. 배포 때마다 gh-pages의 내용이 통째로 교체되고, 이미지와 static 파일도 매번 다시 처리되는 것을 보고 "이래도 되나" 싶어 정리했다.

💡 바쁜 사람을 위한 요약
1. 매 배포마다 전체 교체는 이 방식의 기본 동작이며, 규모가 작으면 부담이 거의 없다.
2. 배포 브랜치 기록이 쌓이는 것은 force_orphan: true로 막을 수 있다.
3. 설치 시간은 requirements.txt 하나로 모으고 pip 캐시를 켜서 줄인다.
4. 빌드 산출물은 캐시하지 않고 매번 깨끗하게 만드는 편이 안전하다.


1. 배포 구조 한눈에 보기

  1. main에 push하면 워크플로가 실행된다.
  2. 저장소를 체크아웃하고 Python을 설치한다.
  3. python build.py로 docs/를 만든다.
  4. peaceiris/actions-gh-pages가 docs/ 내용을 gh-pages 브랜치에 올린다.
  5. GitHub Pages가 gh-pages 브랜치의 루트를 서비스한다.

docs/는 빌드 산출물이라 main에는 커밋하지 않고, 배포 전용 브랜치에만 올라간다.

2. 매번 전체 교체해도 괜찮을까

이 배포 액션의 기본 동작이 "브랜치 내용을 새 빌드로 교체하는 커밋 한 번"이다. 정적 사이트 배포에서 흔한 방식이다.

  • git은 내용이 같은 파일을 같은 객체로 저장한다. 그래서 바뀌지 않은 HTML과 이미지는 저장소 용량을 거의 늘리지 않는다.
  • 문제가 될 수 있는 것은 큰 바이너리를 자주 바꿔 올릴 때다. 이미지나 PDF가 많고 자주 바뀌면 기록이 눈에 띄게 불어날 수 있다.
  • 사이트가 작을 때는 빌드와 배포가 짧게 끝나므로 증분 배포를 따로 만드는 복잡함이 이득보다 크다. 이번에 단계별 소요 시간을 직접 재 보지는 않았다.

3. 초기에 적용해 두면 좋은 설정 세 가지

force_orphan으로 배포 브랜치 기록 정리

force_orphan: true를 켜면 gh-pages가 매번 커밋 하나짜리로 새로 만들어진다. 배포 브랜치의 과거 기록은 필요하지 않고, 원본 기록은 main에 남기 때문에 문제가 없다. 용량이 커진 뒤에 켜도 되지만 처음부터 켜 두면 신경 쓸 일이 없다. 켜는 첫 배포 때 기존 gh-pages 기록은 한 번 사라진다.

requirements.txt로 의존성 한곳에 모으기

워크플로 안에서 패키지를 직접 나열하면 로컬 환경과 어긋나기 쉽다. requirements.txt에 Markdown, PyYAML, python-frontmatter, Pygments를 모으고 워크플로는 pip install -r requirements.txt만 실행하게 했다. 새 패키지를 쓰면 이 파일만 고치면 된다.

pip 캐시

actions/setup-python의 cache: pip를 켜면 다운로드한 패키지를 다음 실행에서 재사용한다. 캐시 키가 될 파일을 cache-dependency-path: requirements.txt로 지정했다. 패키지 수가 적어서 절약되는 시간은 크지 않을 수 있다.

- uses: actions/setup-python@v5
  with:
    python-version: "3.11"
    cache: pip
    cache-dependency-path: requirements.txt

- run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
    python build.py

- uses: peaceiris/actions-gh-pages@v4
  with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: ./docs
    force_orphan: true
    cname: devbj.com

4. 이미지 생성과 static 복사는 캐시하지 않는다

빌더는 시작할 때 이전 HTML 산출물을 지우고 static/을 다시 복사한다. 캐시를 쓰면 빨라질 수 있지만 다음 문제가 생긴다.

  • 삭제하거나 이름을 바꾼 글과 이미지가 이전 산출물로 남을 수 있다.
  • 캐시가 낡았을 때 원인을 찾기 어렵다.
  • 규모가 작아 얻는 시간이 적다.

빌드가 눈에 띄게 느려지면 그때 Actions 로그에서 어느 단계가 오래 걸리는지 먼저 확인하고 손대면 된다.

5. 배포할 때 자주 막히는 지점

  • 빈 디렉토리는 git에 올라가지 않는다. content/data처럼 비어 있는 폴더는 CI 체크아웃에 없다. 빌더가 폴더가 없어도 동작해야 하고, 필요하면 .gitkeep을 둔다. 실제로 "content/data 디렉토리가 없습니다" 오류로 배포가 실패한 적이 있다.
  • Pages 설정을 확인한다. 저장소 Settings의 Pages에서 Source가 gh-pages 브랜치(root)로 되어 있어야 한다. 이 설정이 없으면 배포가 성공해도 사이트에서 404가 나올 수 있다.
  • CNAME은 배포 때 같이 만든다. 액션의 cname 옵션으로 도메인 파일을 유지한다.
  • 커밋되지 않은 로컬 파일에 의존하지 않는다. CI는 체크아웃한 상태만 빌드하므로, 새 이미지나 글을 같이 커밋해야 한다.

마무리: 이렇게 정리해 두면 된다

  1. 매번 전체 교체는 정상이고, 지금 규모에서는 부담이 거의 없다.
  2. 처음부터 force_orphan, requirements.txt, pip 캐시를 적용해 두면 나중에 손볼 일이 줄어든다.
  3. 빌드 산출물은 캐시하지 않고 매번 새로 만든다.

위 설정을 적용한 뒤 첫 Actions 실행 결과는 아직 확인하지 못했다. 설치 단계 통과 여부와 소요 시간을 확인하면 이 글에 보강할 예정이다.

광고