본문으로 건너뛰기

Docusaurus + GitHub Pages 출판 가이드

출판 스택 결정 (현행)

영역도구
정적 사이트 생성기Docusaurus 3.10.x (classic preset, docs only)
배포GitHub Pages (workflow: .github/workflows/deploy-docusaurus.yml)
배포 트리거태그 push (v* 패턴) — main push 로는 배포되지 않음
단일 출처manuscript/articles/*.md
빌드 변환docs-docusaurus/scripts/copy-from-manuscript.mjs

영입 원본: book-happtalk 의 multi-tool hub 패턴. 이 프로젝트는 단일 도구만 사용해 hub 패턴을 생략했다 — Docusaurus 산출물이 곧 사이트.

URL 구조

https://blumnai-studio.github.io/tech-writing-harness/
└─ baseUrl
  • url: https://blumnai-studio.github.io — GitHub organization Pages 도메인
  • baseUrl: /tech-writing-harness/ — 저장소명 그대로
  • organizationName: BlumnAI-Studio
  • projectName: tech-writing-harness

저장소 이름이 변경되면 docusaurus.config.ts 의 세 곳을 동시에 갱신해야 한다.

빌드 흐름

manuscript/articles/*.md ← 사람이 작성

│ npm run copy:manuscript
│ (MANUSCRIPT_STATUS_FILTER=published 가 CI 기본)

docs-docusaurus/docs/articles/ ← 자동 생성 (gitignored)

│ npm run build (docusaurus build)

docs-docusaurus/build/ ← 정적 사이트 산출물 (gitignored)

│ actions/upload-pages-artifact → actions/deploy-pages
│ (트리거: git tag v* push)

GitHub Pages

출판 트리거 — 태그 기반

main 브랜치 push 만으로는 사이트가 배포되지 않는다. v* 패턴의 git tag 가 push 되어야 배포가 일어난다 — 사이트 게시를 명시적 결정으로 끌어올린 의도.

태그 컨벤션 (semver)

자리언제 올리는가
MAJOR (v1.0.0 → v2.0.0)사이트 구조 전면 개편, 도구 교체 (Docusaurus → 다른 SSG)
MINOR (v1.0.0 → v1.1.0)새 글 published, 사이드바 구조 변경
PATCH (v1.0.0 → v1.0.1)오탈자 수정, 이미지 교체, 표기 통일 같은 작은 보정

본 프로젝트 내부 하네스 버전(harness/docs/vX.Y.Z.md)과 사이트 태그(vX.Y.Z)는 별도 축으로 흘러간다. 하네스는 정원이 자라는 속도, 사이트 태그는 발행물의 누적 속도.

출판 절차

# 1) 원고 작업 + 검수 + manuscript-architect 가 status: published 로 승급
# (publication-pipeline 의 Stage 1~4)

# 2) main 으로 commit + push (배포 미발동 — 작업 백업만)
git push origin main

# 3) 사이트 발행 결정 — 새 태그 생성
git tag v1.0.0 -m "첫 글 게시 — 010-문서시스템-하네스도입"
git push origin v1.0.0
# → GitHub Actions deploy-docusaurus.yml 가 발동

# 4) 워크플로우 상태 확인
gh run list --workflow=deploy-docusaurus.yml --limit 3

# 5) 성공 후 사이트 URL 확인 (run summary 또는 repo Settings → Pages)

긴급 수동 배포

태그 없이 즉시 배포해야 할 때 (예: 핫픽스 검증):

gh workflow run deploy-docusaurus.yml --ref main

workflow_dispatch 트리거가 발동된다. 단, 정상 출판 흐름은 태그를 통하는 것이 원칙.

copy-from-manuscript.mjs 동작

  1. manuscript/ walk → .md 파일 수집
  2. frontmatter 파싱 → status 가 필터값에 포함되어야 통과
  3. 파일명에서 slug 추출 → frontmatter 에 id / slug 명시 주입 (Docusaurus 가 prefix 010- 을 자동 제거하는 동작 차단)
  4. ordersidebar_position 매핑
  5. 상대경로 이미지: manuscript/ 바깥이면 docs-docusaurus/docs/_assets/<parent>/ 로 복사 + 경로 재작성
  6. {{변수}} → 백틱 inline code (MDX JS 평가 회피)

환경변수

변수기본효과
MANUSCRIPT_STATUS_FILTERpublished콤마 구분. 예: draft,review,published

CI는 기본값 그대로. 로컬 미리보기 시 작성자가 토글.

GitHub Pages 활성화 (저장소 처음 셋업 시)

  1. GitHub repo → Settings → Pages
  2. Source: GitHub Actions 선택 (Deploy from a branch 가 아님!)
  3. Pages visibility: 저장소가 internal / private 인 경우 별도로 Public 선택 (GitHub Enterprise Cloud 기능 — 코드는 비공개 유지하면서 Pages만 공개 게시)
  4. 첫 워크플로우 실행: Actions 탭 → Deploy · Docusaurus → GitHub Pages → Run workflow
  5. 성공 후 환경 URL 확인 (workflow summary 의 deployment URL)

본 프로젝트(BlumnAI-Studio/tech-writing-harness)는 internal 가시성으로 운영하면서 Pages 만 Public 으로 게시한다. 소스는 조직 내부에서만 보이고, 발행물은 누구나 읽을 수 있다.

권한

워크플로우의 permissions 블록이 필수:

permissions:
contents: read
pages: write
id-token: write

조직 정책에서 Actions Pages 배포가 차단되어 있으면 organization → Settings → Actions → General 에서 허용.

트러블슈팅

빌드 단계

증상진단조치
npm install 의존성 해석 실패Node 버전 확인setup-node 의 node-version: '20' 과 로컬 일치
copy-from-manuscript.mjs 가 0개 복사status 필터 mismatchMANUSCRIPT_STATUS_FILTER 환경변수 확인. manuscript 에 status: published 글이 실제로 있는지
Broken link warn내부 링크의 상대경로 오류같은 articles/ 의 다른 글로 가는 링크는 ./<slug> 형태. onBrokenLinks: 'warn' 이라 빌드는 통과하나 사이트에서 404
Broken markdown image warnmanuscript의 이미지 src 가 존재하지 않음copy 스크립트의 [copy] WARN image not found 로그에서 누락 파일 식별
MDX 파서 오류 (Unexpected token)본문에 <...> 또는 {...} 형태 텍스트.md 만 사용 + {{변수}} 는 자동 escape 됨. 그래도 깨지면 백틱으로 명시 escape

워크플로우 등록/파싱 단계 (v1.0.0 사이클에서 학습)

증상진단조치
워크플로우가 gh run listname: .github/workflows/<>.yml (파일 경로) 으로 표시YAML 파싱 실패 — GitHub Actions 가 name: 필드를 읽지 못함로컬 python -c "import yaml; yaml.safe_load(open(...))" 로 정확한 줄·열 식별
step name:(status filter: published) 같이 콜론+공백이 들어가면 즉시 실패YAML 매핑 키:값으로 잘못 파싱step name 을 큰따옴표로 감싼다: name: "Copy manuscript to docs (status filter: published)"
워크플로우는 등록됐는데 job 이 0초만에 실패, annotation 에 is not allowed to deploy to <environment> due to environment protection rulesenvironment 의 deployment branch policy 가 태그를 허용하지 않음gh api -X POST repos/<owner>/<repo>/environments/<env>/deployment-branch-policies -f name='v*' -f type='tag'
gh api .../pages"public": false 인데 발행물을 공개하고 싶다internal/private repo 의 Pages 기본 가시성gh api -X PUT repos/<owner>/<repo>/pages -f public=true — Enterprise Cloud 기능

배포 단계

증상진단조치
401/403 deploy 실패Pages 권한 누락repo Settings → Pages → Source: GitHub Actions
페이지 404 (URL은 맞는데)baseUrl mismatchbaseUrl: '/tech-writing-harness/' 와 실제 저장소명 일치 확인
asset 404 (이미지 깨짐)_assets/ 복사 실패 또는 경로 깨짐빌드 산출물의 build/articles/<slug>/_assets/ 존재 확인
사이트가 옛 버전 그대로캐시 또는 워크플로우 실패Actions 탭에서 최근 실행 상태 확인. concurrency 그룹 pages 가 cancel 되었는지

Pages 환경 (cosmetic)

증상조치
다크모드가 시스템 설정 무시themeConfig.colorMode.respectPrefersColorScheme: true 확인
한국어 검색 불가기본 검색만 제공. Algolia DocSearch 도입 검토
사이드바가 어색sidebars.ts 의 카테고리 라벨 및 dirName 수정

채택 의사결정 기록

결정이유
Docusaurus만 사용 (multi-tool hub 안 함)단일 사이트로 충분. hub 패턴은 도구가 2개 이상일 때만 가치
버전 디렉터리 없음 (docs-docusaurus/v1/ 가 아님)아직 다중 버전 필요 없음. 필요해지면 그때 docs-docusaurus/v2/ 추가하고 hub 패턴 검토
docs preset (블로그 X)manuscript-architect 의 frontmatter/status/order 흐름이 docs 와 잘 맞음. 글이 시간순 정렬이 본질이면 blog preset 으로 전환 검토
routeBasePath: '/'사이트의 root 가 곧 문서. /docs/ 접두사 없음

전환을 검토할 신호:

  • 글의 발견이 시간순이 더 자연스러워질 때 → blog preset
  • 다국어/다중 버전 도입 → hub 패턴 영입
  • 검색 만족도가 낮을 때 → Algolia DocSearch