GitHub Pages로 배포하기
- GitHub Pages는 Actions에서 빌드한 정적 사이트를 게시할 수 있다.
- 이 저장소의 배포 워크플로는 기본적으로 수동 실행용이다. 자동 배포는 Pages 설정과 push 트리거를 함께 맞춘다.
- 이 저장소는 루트와 하위 경로 배포를 지원한다. site와 base를 설정하면 본문·덱 이동·이미지·검색에 게시 경로가 적용된다.
GitHub에 저장소를 올린 사람이 다른 서비스 계정 없이 사이트를 공개하는 경로다.
설명용 예제는 study-notes 저장소를 https://<계정>.github.io/study-notes/에 게시하는 프로젝트 사이트다.
이 페이지는 GitHub Pages를 쓰기로 했다면 무엇을 설정해야 main에 푸시할 때마다 배포되는가에 답한다.
의도하지 않은 Pages 실행을 발견했다면 자동 실행 조건과
Pages를 끄는 방법부터 확인한다.
웹으로 공유하기에서 로컬 확인과 공개 배포의 차이를 먼저 볼 수 있다.
이 장에서 처음 나오는 말3개
GitHub Pages- GitHub이 저장소의 정적 사이트를 웹으로 제공하는 기능. 이 페이지에서는 Actions가 빌드한 dist/를 게시한다.
GitHub Actions- GitHub이 저장소 이벤트에 맞춰 실행하는 CI. 여기서는 npm run build를 실행해 dist/를 만든다.
basebase path- 사이트가 도메인 루트가 아니라 /repo/ 같은 하위 경로에 놓일 때 모든 링크 앞에 붙는 경로.
private 저장소는 요금제부터 확인한다
섹션 제목: “private 저장소는 요금제부터 확인한다”GitHub Free에서는 public 저장소만 Pages를 사용할 수 있다. 개인·조직의 무료 요금제 모두 private 저장소에서는 지원하지 않는다. GitHub.com의 Pro·Team·Enterprise Cloud에서는 private 저장소도 지원하므로, “private이면 항상 Pages를 쓸 수 없다”는 뜻은 아니다. 공식 지원 조건을 먼저 확인한다.
무료 요금제에서 public 저장소를 private으로 바꿨다면 Pages를 계속 사용할 수 없다. Settings → Pages에 설정 대신 업그레이드 안내가 보이면 이 조건을 확인한다. Actions 목록에 과거 Pages 실행이 남아 있다는 것만으로 현재도 배포가 활성화되어 있다고 판단하지 않는다. 저장소를 다시 공개해 끄기 메뉴를 찾을 필요는 없다.
주소 형태부터 정한다
섹션 제목: “주소 형태부터 정한다”GitHub Pages는 저장소 이름에 따라 주소가 달라지고, 그 차이가 설정 방법을 가른다.
| 형태 | 주소 | 저장소 이름 | base |
|---|---|---|---|
| 프로젝트 사이트 — 기본 예제 | https://<계정>.github.io/study-notes/ | study-notes | /study-notes |
| 사용자 사이트 | https://<계정>.github.io/ | <계정>.github.io | / 또는 생략 |
프로젝트 사이트는 저장소 이름을 유지하고 저장소마다 사이트를 만들 수 있다.
사용자 사이트를 쓴다면 아래 설정에서 base를 /로 둔다. 빌드·업로드·배포 워크플로는 같다.
본문에는 /starlight/intro/처럼 사이트 안의 문서 주소를 그대로 쓴다.
저장소 이름을 모든 링크에 넣을 필요는 없다. 게시 경로는 빌드할 때 공통 처리에서 붙인다.
site와 base를 구분해 설정한다
섹션 제목: “site와 base를 구분해 설정한다”src/config/site.mjs의 기본 주소와 경로를 바꾼다. astro.config.mjs가 이 값을 읽는다.
아래는 프로젝트 사이트의 설정 예다.
import { normalizeBase } from '../utils/site-path.mjs';
export const site = process.env.SITE_URL || 'https://<계정>.github.io';export const base = normalizeBase(process.env.SITE_BASE || '/study-notes/');<계정>과 study-notes는 실제 계정·저장소 이름으로 바꾼다.
| 설정 | 역할 | 사내 사이트에서도 필요한가 |
|---|---|---|
site | canonical·sitemap 등 절대 주소를 만들 때 쓸 기준 주소 | SEO가 불필요해도 다른 사이트 주소를 남기지 않는다 |
base | 페이지·자산이 제공되는 하위 경로 | 하위 경로 배포라면 필요하다. CSS·JS·링크가 올바른 위치를 요청하기 위한 값이다 |
Astro의 site·base 정의처럼 두 값의
목적은 다르다. 예를 들어 /study-notes/에 게시했는데 자산을 /_astro/…로 요청하면
브라우저는 사이트 바깥을 찾는다. 검색엔진 사용 여부와 관계없이 화면이 깨질 수 있다.
설정 파일 대신 SITE_URL·SITE_BASE 환경 변수로 값을 덮어쓸 수도 있다.
준비된 워크플로는 Pages의 게시 주소를 자동으로 읽어 넣지 않으므로, 위 기본값을 저장하거나
빌드 단계에 두 환경 변수를 전달한다. base는 /team/notes/처럼 여러 단계여도 된다.
프로젝트 사이트의 하위 경로를 확인한다
섹션 제목: “프로젝트 사이트의 하위 경로를 확인한다”Astro의 base만으로 직접 쓴 모든 링크가 바뀌지는 않는다. 이 저장소는 본문 링크와 공용
컴포넌트에 경로 처리를 추가했다. /starlight/intro/는 base가 /study-notes/이면
/study-notes/starlight/intro/로 렌더된다. 외부 URL·페이지 안의 #절-주소·코드 예제는 유지한다.
Astro base 안내의
import.meta.env.BASE_URL과 빌드 설정을 사용한다.
설정 파일을 아직 바꾸지 않고 확인하려면 터미널에서 다음을 실행한다.
SITE_URL=https://YOUR-ACCOUNT.github.io SITE_BASE=/study-notes/ npm run checkSITE_URL=https://YOUR-ACCOUNT.github.io SITE_BASE=/study-notes/ npm run previewYOUR-ACCOUNT와 study-notes는 실제 값으로 바꾼다. preview가 출력한 로컬 주소의
/study-notes/를 연다. 설정 파일에 값을 저장했다면 환경 변수 없이 같은 명령을 쓸 수 있다.
빌드와 preview에 같은 경로를 사용한다.
| 확인할 것 | 예상 결과 |
|---|---|
| 랜딩·덱 전환·본문 링크 | 이동 후에도 /study-notes/ 아래에 있다 |
| 이미지·D2·이미지 확대 | 그림과 확대 화면이 정상으로 열린다 |
| 전역 검색 | 결과를 누르면 /study-notes/ 아래 문서로 이동한다 |
| canonical·sitemap | 실제 공개 도메인과 /study-notes/를 포함한다 |
npm run check는 게시 경로를 반영해 페이지·절·이미지·스크립트·스타일·폰트 참조와
canonical·sitemap을 검사한다. 공용 경로 처리를 바꿀 때는 npm run check:base로
/study-notes/와 /team/notes/ 두 경우도 빌드·검사한다. 검색 결과 이동과 이미지 확대는
대표 화면에서 확인한다. 로컬 검사가 통과한 것과 GitHub Pages에 실제 게시된 것은 구분한다.
사내 GHE라면 실제 Pages 주소를 기준으로 한다
섹션 제목: “사내 GHE라면 실제 Pages 주소를 기준으로 한다”사내 GitHub Enterprise Server(GHES)에서도 하위 경로는 필요하다. GHES의 기본 Pages 주소는 서브도메인 분리 설정에 따라 달라지므로, 저장소 Settings → Pages에 표시되는 게시 주소를 기준으로 나눈다.
| 게시 주소 예시 | site | base |
|---|---|---|
https://pages.git.example.com/team/study-notes/ | https://pages.git.example.com | /team/study-notes |
https://git.example.com/pages/team/study-notes/ | https://git.example.com | /pages/team/study-notes |
git.example.com은 가상의 사내 GHES 주소다. 사용자 사이트도 GHES에서는 소유자 경로가
붙을 수 있으므로 GitHub.com의 “사용자 사이트면 base 생략” 규칙을 그대로 적용하지 않는다.
아래 워크플로의 action 버전은 GitHub.com 기준이다. GHES에는 서버 버전에 맞는 Pages 워크플로 안내와 deploy-pages 호환표를 먼저 적용한다. 러너·action 사용 허용과 npm·D2 다운로드 경로도 사내 환경에 맞아야 한다. 주소 설정과 GHES 워크플로 호환성은 별도로 확인할 항목이다.
Pages가 워크플로를 만들어 주는가
섹션 제목: “Pages가 워크플로를 만들어 주는가”Pages의 Source 설정에 따라 실행 주체가 달라진다.
| Source | 누가 빌드·배포를 실행하는가 |
|---|---|
| Deploy from a branch + 브랜치·폴더 선택 후 저장 | 선택한 브랜치에 push하면 GitHub이 자동 Pages 워크플로를 실행한다 |
| GitHub Actions | 저장소에 작성한 워크플로가 자신의 on 조건에 따라 실행된다 |
Deploy from a branch는 자동 워크플로를 쓴다
섹션 제목: “Deploy from a branch는 자동 워크플로를 쓴다”예를 들어 Deploy from a branch → main → /(root) → Save로 설정하면, 이후 main에
직접 push할 때 pages build and deployment가 자동 실행된다. .github/workflows/에
배포 YAML을 만들지 않아도 동작한다. GitHub이 관리하는 워크플로이므로 저장소의 deploy.yml에서
push 트리거를 주석 처리해도 이 실행은 멈추지 않는다.
브랜치 게시 방식의 동작이다.
기본 빌더는 Jekyll이다. Astro 소스가 있는 main의 루트를 고르면 .astro 파일의
--- 안 코드를 YAML로 읽다가 Invalid YAML front matter 같은 오류로 실패할 수 있다.
로그에 Build with Jekyll이 보이면 Source 설정부터 확인한다.
빈 파일 **.nojekyll**을 게시 원본의 최상단에 두면 Jekyll 빌드만 생략한다.
자동 워크플로와 배포는 계속되며, Astro 빌드를 대신하지 않는다. 이 방식으로 Astro 사이트를
게시하려면 미리 빌드한 dist/의 내용과 .nojekyll을 별도 배포 브랜치에 올려야 한다.
Jekyll 생략 조건을 따른다.
GitHub Actions는 저장소의 워크플로를 쓴다
섹션 제목: “GitHub Actions는 저장소의 워크플로를 쓴다”Settings → Pages → Source → GitHub Actions를 고르면
GitHub이 워크플로 템플릿을 제안한다.
Astro용 템플릿도 있다.
템플릿을 선택해 내용을 확인하고 커밋하면 .github/workflows/에 YAML 파일이 생긴다.
Source 선택만으로 npm run build가 자동 설정되는 것은 아니다.
이 설정은 워크플로가 전달한 결과를 Pages에 게시하는 방식을 선택한다.
특정 YAML 파일이나 dist/ 폴더를 자동으로 감시하지 않는다. 워크플로가 빌드 결과를
아티팩트(파일 묶음)로 업로드하고 deploy-pages로 게시를 요청해야 사이트가 갱신된다.
업로드·배포 절차를 따른다.
Astro 소스를 GitHub에서 빌드해 배포하는 이 방식에는 워크플로 파일이 필요하다.
저장소에 준비된 워크플로
섹션 제목: “저장소에 준비된 워크플로”이 저장소에는 .github/workflows/deploy.yml이 들어 있으므로 템플릿을 새로 만들 필요가 없다.
Astro 공식 안내를 바탕으로 전체 Git 이력을 받도록 했다.
main push 트리거는 주석으로 준비해 두었으며, GitHub Pages를 쓸 때 해제한다.
check.yml은 검사용이고, deploy.yml은 배포용이다.
name: Deploy to GitHub Pages
on: # push: # branches: [main] workflow_dispatch:
permissions: contents: read pages: write id-token: write
concurrency: group: github-pages cancel-in-progress: false
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 with: # 랜딩 카드의 "마지막 수정"이 git log에서 나오므로 전체 이력을 받는다. fetch-depth: 0 - uses: withastro/action@v6 with: build-cmd: npm run build deploy: needs: build runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - uses: actions/deploy-pages@v5 id: deployment각 줄이 맡는 일은 다음과 같다.
| 부분 | 왜 필요한가 |
|---|---|
주석 처리된 push·branches | 두 줄의 주석을 해제하면 main push마다 배포한다. 주석 상태에서는 push로 실행되지 않는다 |
workflow_dispatch | Actions 화면에서 수동으로도 실행할 수 있게 한다 |
fetch-depth: 0 | 기본값 1이면 모든 문서가 같은 날짜로 보인다. 저장소의 prepare-git-history.mjs는 Cloudflare Pages에서만 동작하므로 여기서는 checkout이 직접 전체 이력을 받아야 한다 |
withastro/action@v6 | lockfile로 패키지 관리자를 감지해 설치·빌드하고 산출물을 Pages 아티팩트로 올린다. package-lock.json이 있으므로 npm을 쓴다. Node 버전은 실행 로그에서 저장소의 요구 조건인 24 이상인지 확인한다 |
build-cmd: npm run build | package.json의 build 스크립트를 그대로 쓴다. D2 바이너리는 이 안에서 GitHub release에서 내려받는다 |
deploy-pages@v5 | 빌드 job이 올린 아티팩트를 Pages에 게시한다 |
수동 실행과 Disable workflow의 차이
섹션 제목: “수동 실행과 Disable workflow의 차이”deploy.yml의 기본값은 자동 실행 이벤트 없이 수동 실행만 받는 것이다.
GitHub의 Disable workflow는 수동 실행까지 막는 별도 상태이며, YAML에 disabled: true처럼
기본값으로 저장하는 항목은 없다. 파일을 유지한 채 완전히 꺼 두려면 GitHub에 파일이 올라간 뒤
Actions → Deploy to GitHub Pages → ⋯ → Disable workflow를 누른다.
다시 사용할 때는 Enable workflow를 누른다.
GitHub의 비활성화 안내에
UI·CLI·API 방법이 있다.
이 메뉴는 저장소에 작성한 Deploy to GitHub Pages 워크플로를 대상으로 한다.
GitHub이 자동 생성한 pages build and deployment에 Disable workflow가 보이지 않으면
아래 Pages 설정에서 끄는 절차를 따른다.
Pages를 설정하고 자동 배포를 켠다
섹션 제목: “Pages를 설정하고 자동 배포를 켠다”프로젝트 사이트는 위 주소 설정과 로컬 검증을 마친 뒤 진행한다.
-
저장소 Settings → Pages로 간다.
-
Build and deployment → Source에서 GitHub Actions를 고른다. 준비된 파일을 쓰므로 템플릿 생성은 건너뛴다.
-
.github/workflows/deploy.yml에서push와branches두 줄의 주석을 해제한다..github/workflows/deploy.yml — 주석 해제 후 on 부분 on:push:branches: [main]workflow_dispatch: -
src/config/site.mjs의 주소·경로 설정과 워크플로 변경을main에 커밋·푸시한다. Actions → Deploy to GitHub Pages에서 실행을 확인한다. 주석을 해제한 이번 push부터 배포된다. -
두 job이 초록색이 되면 Settings → Pages 상단에 게시된 주소가 보인다.
이후 문서를 수정해 main에 푸시할 때마다 빌드·배포가 실행된다. 로컬에서 커밋만 한 상태에서는
실행되지 않고, GitHub에 push가 도착해야 시작한다.
프로젝트 사이트의 예상 결과는 https://<계정>.github.io/study-notes/starlight/intro/가 열리고,
canonical에도 같은 게시 경로가 들어 있는 것이다. 사용자 사이트는 /study-notes를 뺀다.
curl -s 'https://YOUR-ACCOUNT.github.io/study-notes/starlight/intro/' | grep -o '<link rel="canonical"[^>]*>'위 명령의 YOUR-ACCOUNT와 study-notes는 실제 값으로 바꾼다. 첫 실행이 실패하면
실패한 단계의 로그를 읽고 Node 버전·의존성 설치·D2 다운로드·Pages 권한을 확인한다.
수동 실행과 자동 배포 중지
섹션 제목: “수동 실행과 자동 배포 중지”커밋을 추가하지 않고 다시 배포하려면 Actions → Deploy to GitHub Pages → Run workflow에서
main을 골라 실행한다. 이 메뉴는
워크플로 파일이 기본 브랜치에 있어야 나타난다.
자동 배포를 멈추고 수동 실행만 남기려면 push와 그 아래 branches 두 줄을 다시 주석 처리해
커밋·푸시한다. 이것은 deploy.yml의 자동 실행만 멈춘다.
이미 게시된 사이트는 워크플로를 비활성화해도 계속 제공된다.
브랜치 자동 배포와 Pages를 끈다
섹션 제목: “브랜치 자동 배포와 Pages를 끈다”Cloudflare Pages 등 다른 호스팅을 쓰고 GitHub Pages가 필요 없다면 게시 소스를 해제한다. 저장소의 Pages 설정을 변경할 권한이 있는 계정으로 진행한다.
-
저장소 Settings → Pages로 간다.
-
Build and deployment → Source → Deploy from a branch를 고른다.
-
Branch → None → Save로 저장한다.
이 절차는 브랜치 자동 배포를 끄고 GitHub Pages 사이트도 삭제한다. 저장소 파일과
Cloudflare Pages 배포는 유지된다. GitHub의 Pages 삭제 절차다.
직접 작성한 deploy.yml에도 push 트리거를 켜 두었다면 위 방법으로 별도 중지한다.
저장 후 Branch가 None인지 확인하고, 다음 정상 push에서 새 pages build and deployment 실행이
생기지 않는지 본다. 과거 실행 기록이 남는 것은 정상이다. 다시 브랜치 배포를 쓰려면 게시할
브랜치·폴더를 선택해 저장한다. Astro 소스를 빌드할 목적이라면 Source를 GitHub Actions로
바꾸고 이 페이지의 배포 설정을 따른다.
확인할 제한
섹션 제목: “확인할 제한”- GitHub.com의 일반 Pages는 비공개 저장소여도 사이트가 공개될 수 있다. GHES의 접근 범위는 사내 Pages 정책·설정을 확인한다. 저장소 공개 범위만으로 판단하지 않는다.
- 빌드는 GitHub이 제공하는 러너에서 돌며 외부 다운로드가 가능하다. D2 바이너리 다운로드가 여기 의존한다.
- 준비된 워크플로에는 브랜치별 미리보기가 없다. 다른 브랜치를 미리 보려면 로컬
npm run preview를 쓴다. - 위 워크플로는 2026-09-30 공식 문서와 이 저장소의 스크립트를 대조했고, 실제 GitHub Pages 배포로 실측한 것은 아니다. lockfile 감지로 npm이 선택되는지는 첫 실행 로그로 확인한다.
이해 확인
섹션 제목: “이해 확인”사내 Pages라 검색엔진에 노출하지 않는다면 base를 생략해도 될까? 아니다.
게시 주소가 /team/study-notes/ 아래라면 링크·자산도 그 경로를 포함해야 한다.
site의 대표 주소 역할과 base의 경로 역할을 나눠 설정한다. 본문에 저장소 이름을 직접 붙이지 않는다.