콘텐츠로 이동

레포 아키텍처: 로컬 ↔ GitHub ↔ Cloudflare ↔ Wrangler

wine-research 레포가 로컬 작업 환경부터 공개 위키 사이트까지 어떻게 흘러가는지, 각 계층이 어떤 역할을 하는지, 그리고 무엇이 어떤 트리거로 동기화되는지 한 장에 정리한다.

요약: 로컬에서 마크다운을 쓰고, _workspace/를 진실의 원천으로 삼아 → GitHub에는 원본을 보관하고 → Astro/Starlight가 위키 사이트로 빌드하고 → Wrangler CLICloudflare Pagesproduction 브랜치로 업로드한다. GitHub와 Cloudflare는 직접 연결돼 있지 않다(이게 핵심 함정).


┌────────────────────────────────────────────────────────────────────────────┐
│ [1] 로컬 워크스테이션 │
│ │
│ /Users/yejinkim/dev/wine-research/ │
│ ├── _workspace/ ← 진실의 원천 (모든 .md 리서치/스펙/플레이북) │
│ │ ├── 01_sensory_research.md │
│ │ ├── 50_label_recognition_research.md │
│ │ ├── 53_repo_architecture.md ← (이 문서) │
│ │ └── … │
│ ├── CLAUDE.md ← 하네스 정의·변경 이력·트러블슈팅 노트 │
│ └── site/ ← Astro Starlight 위키 빌드 │
│ ├── scripts/sync-docs.mjs (workspace → src/content/docs 복사) │
│ ├── src/content/docs/ (sync가 매번 reset+재생성) │
│ ├── astro.config.mjs (사이드바·로케일 정의) │
│ └── dist/ (astro build 산출물, .gitignore됨) │
└──────────────┬──────────────────────────────────┬──────────────────────────┘
│ │
│ git push origin main │ npm run deploy
│ (소스 + 작업 이력 보존) │ (정적 사이트 업로드)
▼ ▼
┌────────────────────────────────────┐ ┌────────────────────────────────────┐
│ [2] GitHub │ │ [3] Cloudflare Pages │
│ │ │ │
│ rocher71/wine-research │ │ project: wine-wiki │
│ ├── branch: main │ │ production branch: production │
│ ├── _workspace/*.md (원본) │ │ public URL: │
│ ├── CLAUDE.md │ │ https://wine-wiki-kg5 │
│ └── site/ (소스만, dist 제외) │ │ .pages.dev │
│ │ │ │
│ 역할: 코드/문서 버전 관리, 협업 │ │ 역할: 사이트 호스팅, CDN, HTTPS │
└────────────────────────────────────┘ └─────────────────▲──────────────────┘
│ HTTPS API
│ upload dist/
┌───────────────┴────────────────┐
│ [4] Wrangler CLI │
│ │
│ site/node_modules/wrangler │
│ (devDependency, ^4.90.0) │
│ │
│ `wrangler pages deploy dist │
│ --project-name=wine-wiki │
│ --branch=production` │
│ │
│ 역할: Cloudflare API 클라이언트│
│ (로컬→Cloudflare 단방향 푸시)│
└────────────────────────────────┘

로컬 = 작업장 / GitHub = 보관소 / Cloudflare = 게시판 / Wrangler = 게시판에 붙이는 손

GitHub와 Cloudflare 사이에는 자동 동기화가 없다. Cloudflare Pages가 GitHub 리포지토리를 “watch”하도록 연결돼 있지 않다. 두 곳은 각각 독립적으로 로컬에서 푸시된다.


2. 책임 매트릭스 (어디서 무엇을)

섹션 제목: “2. 책임 매트릭스 (어디서 무엇을)”
계층무엇을 보관/실행트리거사람이 직접 만지는가
로컬 _workspace/모든 리서치/스펙/플레이북 원본사람이 직접 작성 또는 에이전트가 생성
로컬 site/src/content/docs/사이트 빌드 입력 (재생성됨)npm run sync (혹은 dev/build 안에서 자동)❌ (sync가 매번 wipe)
로컬 site/dist/정적 HTML/CSS/JS 빌드 산출물astro build
GitHub main소스(_workspace, site, CLAUDE.md)git push
Cloudflare production env게시되는 사이트wrangler pages deploy --branch=production
Cloudflare Preview env미리보기용 (해시 URL)wrangler pages deploy (기본값)

3. 가장 헷갈리는 부분: _workspace/site/src/content/docs/

섹션 제목: “3. 가장 헷갈리는 부분: _workspace/ ↔ site/src/content/docs/”
_workspace/ site/src/content/docs/
┌──────────────────────┐ ┌──────────────────────┐
│ 01_sensory_research │ sync-docs │ tasting/ │
│ 02_flavor_research │ .mjs │ 01_sensory_… │
│ 13_user_feedback │ ─────────────► │ 02_flavor_… │
│ 15_design_system │ (매번 reset) │ feedback/13_… │
│ 30_app_spec_v1 ❌ │ │ tech/15_… │
│ 45_weekly_report ❌ │ │ market/10_… │
│ 50_label_recog │ │ misc/… │
│ 53_repo_architecture │ │ tech/53_repo_… │
└──────────────────────┘ └──────────────────────┘
※ 30~39, 40~49 prefix는
EXCLUDE 정규식으로 제외
(앱 사양·작업 보고는 비공개)

site/scripts/sync-docs.mjs:18-22GROUPS 정의:

tasting: 01-05, 17사이드바 "테이스팅 차원"
regions: 06-09"산지"
feedback: 13, 16"피드백"
tech: 14, 15, 50-59"기술/엔지니어링"
market: 10-29, 60-69"시장·마케팅 전략"
(fallback) misc"기타"

위→아래 순서로 매칭한다. market의 10-29 광역 매치보다 feedback/tech의 명시 번호를 먼저 두기 때문에 13·14·15·16번이 의도한 그룹으로 들어간다.

EXCLUDE 패턴: /^[34][0-9]_/ → 3039(앱 구현 사양), 4049(작업 보고)는 위키에 올라가지 않는다.


사람 npm run deploy Cloudflare
│ │ │
│ npm run deploy │ │
├─────────────────────────►│ │
│ │ │
│ ├─ [build] npm run sync │
│ │ ├─ resetDocs() ── docs/ wipe │
│ │ ├─ syncWorkspace() ── 라우팅 │
│ │ └─ writeIndex() ── splash 생성 │
│ │ │
│ ├─ [build] astro build │
│ │ └─ → site/dist/ │
│ │ │
│ ├─ wrangler pages deploy dist │
│ │ --project-name=wine-wiki │
│ │ --branch=production │
│ │ ──────────────────────────────►│ Upload
│ │ │ Production env
│ │ ◄──────────────────────────────│ deployment URL
│ │ │
│ "Deployed to │ │
│ https://wine-wiki-kg5.pages.dev" │
│◄─────────────────────────┤ │

소요 시간: 정상 시 sync(~1s) + build(~30-60s) + upload(~30-90s) = 총 2-3분.


5. 환경/브랜치 매핑 — 실수하기 가장 쉬운 지점

섹션 제목: “5. 환경/브랜치 매핑 — 실수하기 가장 쉬운 지점”
로컬 git branchWrangler --branchCloudflare 환경결과 URL
main (디폴트)미지정 → mainPreviewhttps://<hash>.wine-wiki-kg5.pages.dev (해시 URL만)
mainproductionProductionhttps://wine-wiki-kg5.pages.dev (정식)

왜 함정인가: wrangler의 --branch 디폴트는 “현재 git branch명”. Cloudflare Pages 대시보드에서 production branch가 production으로 설정돼 있는데, 우리 로컬 작업은 main에서 이루어진다. 둘이 일치하지 않아 정식 URL이 며칠 전 상태로 멈춰 보인다. → T-002 참조.

해결: site/package.json:9--branch=production을 영구 박아둠.

"deploy": "npm run build && wrangler pages deploy dist --project-name=wine-wiki --branch=production",
"deploy:preview": "npm run build && wrangler pages deploy dist --project-name=wine-wiki"

Terminal window
cd site && npm run deploy
Terminal window
cd site && npm run deploy:preview
Terminal window
cd site && npm run dev # http://localhost:4321
Terminal window
git add _workspace/ CLAUDE.md site/
git commit -m ""
git push origin main
Terminal window
cd site && npx wrangler pages deployment list --project-name=wine-wiki
# Environment 열에서 Production / Preview 구분

빌드 hang 복구 (디렉토리 rename 직후)

섹션 제목: “빌드 hang 복구 (디렉토리 rename 직후)”
Terminal window
xattr -dr com.apple.provenance ./site && \
rm -rf site/node_modules site/.astro site/dist site/.wrangler/tmp && \
cd site && npm install && npm run deploy

7. 누가 어디로 가는가 (파일 → 위키 사이드바)

섹션 제목: “7. 누가 어디로 가는가 (파일 → 위키 사이드바)”
파일명 → 위키 사이드바 그룹 → URL slug
─────────────────────────────────────────────────────────────────────────────────────
01_sensory_research.md → 테이스팅 차원 /tasting/01_sensory_research/
06_burgundy_terroir.md → 산지 /regions/06_burgundy_terroir/
10_vivino_korea_analysis.md → 시장·마케팅 전략 /market/10_vivino_korea_analysis/
13_user_feedback.md → 피드백 /feedback/13_user_feedback/
15_design_system.md → 기술/엔지니어링 /tech/15_design_system/
17_ritual_research.md → 테이스팅 차원 /tasting/17_ritual_research/
30_app_spec_v1.md → ❌ EXCLUDE (비공개) —
45_weekly_report.md → ❌ EXCLUDE (비공개) —
50_label_recognition_research.md → 기술/엔지니어링 /tech/50_label_recognition_research/
53_repo_architecture.md → 기술/엔지니어링 /tech/53_repo_architecture/
60_marketing_plan.md → 시장·마케팅 전략 /market/60_marketing_plan/
65_meta_ads_setup_playbook.md → 시장·마케팅 전략 /market/65_meta_ads_setup_playbook/
wine-tasting-notes-reference.md → 통합 레퍼런스 /synthesis/wine-tasting-notes-reference/

전체 내용은 CLAUDE.md에. 아래는 발생 빈도가 높은 두 가지.

ID증상원인1줄 해결
T-001npm run deploy가 astro build에서 무한 hangmacOS com.apple.provenance xattr (디렉토리 rename 후 Gatekeeper가 native binary 검증으로 stall)xattr -dr com.apple.provenance ./site && rm -rf site/{node_modules,.astro,dist,.wrangler/tmp} && cd site && npm install && npm run deploy
T-002정식 URL에 변경이 안 보임wrangler 기본 --branch=<현재 git branch>(=main)가 Cloudflare의 Preview 환경으로만 푸시. Cloudflare의 production branch는 productioncd site && npx wrangler pages deploy dist --project-name=wine-wiki --branch=production (또는 npm run deploy 사용)

Q. GitHub에 push하면 Cloudflare에도 자동 반영되나? A. 아니다. Cloudflare Pages는 이 레포의 GitHub와 직접 연결돼 있지 않다. npm run deploy를 별도로 실행해야 위키가 갱신된다. (CI/CD를 붙이려면 GitHub Actions에서 wrangler를 호출하는 워크플로를 추가해야 한다 — 현재는 없음.)

Q. _workspace/만 고치면 자동으로 위키에 올라가나? A. 아니다. _workspace/site/src/content/docs/ 복사는 npm run sync(혹은 build/dev/deploy)가 실행될 때만 일어난다. 사람이 명령을 쳐야 한다.

Q. site/src/content/docs/를 직접 고쳐도 되나? A. 안 된다. sync-docs.mjs가 매번 resetDocs()로 해당 디렉토리를 통째로 지운 뒤 _workspace/에서 새로 생성한다. 반드시 _workspace/ 원본을 고쳐야 한다.

Q. Wrangler를 사용자 계정 인증은 어디서? A. wrangler login으로 한 번 인증하면 ~/.config/.wrangler/(또는 macOS 키체인)에 토큰이 보관된다. CI에서 돌리려면 CLOUDFLARE_API_TOKEN 환경변수를 사용한다. 현재 이 레포에는 CI가 없으므로 로컬에서 1회 로그인된 상태로 동작.

Q. 비공개로 두고 싶은 파일은? A. 파일명을 30_39_(앱 사양) 혹은 40_49_(작업 보고)로 짓는다. sync-docs.mjs의 EXCLUDE = /^[34][0-9]_/가 위키 빌드 대상에서 제외한다. 단, GitHub에는 그대로 push되므로 정말 비밀이라면 .gitignore에 추가하거나 레포 외부에 둬야 한다.


10. 변경 시 같이 손대야 하는 파일

섹션 제목: “10. 변경 시 같이 손대야 하는 파일”
변경하고 싶은 것손대는 파일
위키 사이드바 라벨/순서site/astro.config.mjs
파일명 prefix → 그룹 매핑site/scripts/sync-docs.mjs (GROUPS)
위키에서 제외할 prefixsite/scripts/sync-docs.mjs (EXCLUDE)
위키 첫 화면(splash)site/scripts/sync-docs.mjs (writeIndex)
배포 명령 동작site/package.json (scripts)
Cloudflare 프로젝트명·production branchCloudflare Pages 대시보드 + site/package.json의 wrangler 인자
GitHub 원격git remote set-url origin <new-url>