Skip to content

Commit 72d2ede

Browse files
committed
chore: develop → main 머지 [skip-notion]
2 parents 46a056a + 049e3c4 commit 72d2ede

3 files changed

Lines changed: 36 additions & 49 deletions

File tree

.github/workflows/monthly-translate.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ jobs:
2020
- uses: actions/setup-python@v5
2121
with:
2222
python-version: '3.12'
23-
cache: pip
2423

2524
- run: pip install requests
2625

CLAUDE.md

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ docs-web/
5353
│ └── tests/ # notion_to_md.py·md_to_notion.py 단위 테스트
5454
└── .github/workflows/
5555
├── deploy.yml
56-
├── monthly-translate.yml # 매월 1일 EN 번역 자동 실행 (실패 시 빌드 영향 없음)
56+
├── monthly-translate.yml # 매월 1일 EN 번역 자동 실행
5757
├── md-to-notion.yml
5858
├── merge-develop.yml
5959
├── pr-build.yml
@@ -66,7 +66,6 @@ docs-web/
6666

6767
서버와 로컬 모두 프로젝트 루트 `.env` 에서 로드. GitHub Actions는 Secrets로 동일 값 등록.
6868

69-
7069
| 변수 | 역할 |
7170
| --------------------- | ------------------------------------------------------------------------ |
7271
| `NOTION_TOKEN` | Notion Integration 비밀 토큰 |
@@ -80,7 +79,6 @@ docs-web/
8079
| `NOTION_INSTALL` | "설치" DB ID → `docs/install/` |
8180
| `DEEPL_API_KEY` | DeepL Free API 키 — `translate_to_en.py``monthly-translate.yml` Secret |
8281

83-
8482
`server-sync.sh``[ -n "$NOTION_XXX" ]` 조건으로 변수가 없으면 해당 DB sync를 건너뜀.
8583

8684
---
@@ -110,50 +108,49 @@ docs/poc/vision-bench/child.md (slug: "1") → /docs/poc/vision-bench/1
110108
0 */3 * * * /root/docs-web/scripts/server-sync.sh >> /var/log/notion-sync.log 2>&1
111109
```
112110

113-
`server-sync.sh` 실행 흐름: `git checkout main``git pull --rebase` → Notion 8개 DB 병렬 동기화 → `git commit``translate_to_en.py` (변경 파일만 DeepL 번역) → `git commit``push``deploy.yml` 트리거
111+
`server-sync.sh` 실행 흐름:
112+
1. ORIG_BRANCH 저장 + `trap EXIT` 등록 (종료 시 원래 브랜치 복귀 — dev 서버 파일 보호)
113+
2. `git checkout main``git pull --rebase`
114+
3. Notion 8개 DB 병렬 동기화
115+
4. `git commit``git push origin main``deploy.yml` 트리거
116+
5. 스크립트 종료 → trap이 자동으로 원래 브랜치(develop 등)로 복귀
114117

115118
로그 확인: `tail -f /var/log/notion-sync.log`
116119

117-
> ⚠️ **staged files 주의:** git index에 스테이징된 파일(커밋 안 한 `git add`)이 있으면 `git pull --rebase`가 실패해 crontab이 멈춘다. Claude가 main에서 작업할 때는 반드시 커밋까지 완료하고 떠나야 한다. 확인: `git diff --staged --quiet || echo "STAGED"` — 출력이 있으면 커밋 또는 `git restore --staged .` 후 종료.
120+
> ⚠️ **staged files 주의:** git index에 스테이징된 파일(커밋 안 한 `git add`)이 있으면 `git pull --rebase`가 실패해 crontab이 멈춘다. Claude가 작업 후에는 반드시 커밋까지 완료하고 떠나야 한다. 확인: `git diff --staged --quiet || echo "STAGED"` — 출력이 있으면 커밋 또는 `git restore --staged .` 후 종료.
118121
119122
### GitHub Actions 워크플로우
120123

121-
122124
| 파일 | 트리거 | 역할 |
123125
| ----------------------- | -------------------- | ------------------------------------------------------------------- |
124126
| `deploy.yml` | main push | npm build → GH Pages 배포 |
125-
| `monthly-translate.yml` | 매월 1일 KST 11:00 / 수동 | KR docs·blog → DeepL → `i18n/en/` 번역, main에 커밋 (전체 재검사용 백업) |
127+
| `monthly-translate.yml` | 매월 1일 KST 11:00 / 수동 | KR docs·blog → DeepL → `i18n/en/` 번역, main에 커밋 |
126128
| `sync-develop.yml` | 매일 KST 03:00 | main 콘텐츠를 develop으로 머지 (`.notion-sync.json` 충돌 자동 해소) |
127129
| `merge-develop.yml` | 매일 KST 11:00 | develop 코드 변경을 main으로 머지 (콘텐츠 디렉토리 제외, 빌드 게이트 포함) |
128130
| `md-to-notion.yml` | `docs/**/*.md` push | 수동 편집된 md → Notion DB 역업로드 |
129131
| `pr-build.yml` | main·develop PR | 프로덕션 빌드 검증 (깨진 링크·MDX 오류 차단) |
130132

131-
132133
### 커밋 메시지 태그 규칙
133134

134-
135135
| 태그 | 효과 |
136136
| ------------------ | --------------------- |
137137
| `[skip-notion]` | `md-to-notion.yml` 스킵 |
138138
| 커미터가 `server-cron` | `md-to-notion.yml` 스킵 |
139139

140-
141-
`**[skip-notion]` 필수 상황:** Notion에서 내려받은 내용을 다시 올리면 무한 루프가 된다.
140+
**`[skip-notion]` 필수 상황:** Notion에서 내려받은 내용을 다시 올리면 무한 루프가 된다.
142141

143142
- 서버 crontab 커밋 → 자동 부여됨
144143
- Claude가 수동 커밋할 때 `.notion-sync.json`·`docs/` Notion 원본 포함 시 → 반드시 추가
145144
- `design → main` 등 머지 커밋이 `docs/` 파일 포함 시 → 머지 커밋 메시지에도 추가
146145

147146
### 외부 검색 최적화 (SEO) — 2026-06-22 적용
148147

149-
150148
| 항목 | 내용 | 파일 |
151149
| --------------------- | --------------------------------------- | ------------------------------------ |
152150
| Google Search Console | 소유권 인증 완료, `sitemap.xml` 제출됨 | `static/google8226dc54aa85a9f0.html` |
153151
| JSON-LD 구조화 데이터 | `@graph`: Organization + WebSite 타입 | `docusaurus.config.ts``headTags` |
154152
| GitHub 링크 | navbar·footer 모두 `SceneMakerAI` org로 변경 | `docusaurus.config.ts` |
155153

156-
157154
JSON-LD 스키마 참고: [schema.org/WebSite](https://schema.org/WebSite) · [schema.org/Organization](https://schema.org/Organization)
158155
Google Rich Results Test: [https://search.google.com/test/rich-results](https://search.google.com/test/rich-results)
159156

@@ -173,14 +170,12 @@ main (콘텐츠 자동화 전용)
173170
└─ design (장기 유지, UI·CSS·설정 전용)
174171
```
175172

176-
177173
| 작업 유형 | 시작 브랜치 | 머지 대상 | dev 서버 포트 | 담당 |
178174
| ------------------- | --------- | ----------------------- | --------- | ---------- |
179175
| 콘텐츠 (Notion 자동 동기화) || `main` 직접 커밋 *(자동화 전용)* | 3000 | 서버 crontab |
180176
| **모든 코드 변경** | `develop` | `feat/<이름>``develop` | 3001 | **Claude** |
181177
| **main 반영** || `develop``main` | 3000 | **사용자** |
182178

183-
184179
**작업 흐름 (Claude 담당 부분):**
185180

186181
```bash
@@ -232,7 +227,6 @@ git push origin design
232227

233228
## 자주 쓰는 명령어
234229

235-
236230
| 명령어 | 용도 |
237231
| ----------------------- | --------------------------------------------------------------- |
238232
| `npm start` | main 브랜치 dev 서버 (port 3000, KO+EN) |
@@ -241,7 +235,6 @@ git push origin design
241235
| `npm run clear` | Docusaurus 캐시 정리 |
242236
| `npm run typecheck` | TypeScript 검사 (빌드와 무관, IDE 보조) |
243237

244-
245238
**dev 서버 404 / 브랜치 전환 후 캐시 꼬임:** `npm run clear` 후 재시작.
246239

247240
**EN 로케일 접근:** `--locale` 플래그 없이 실행하면 KO (`/`) + EN (`/en/`) 모두 서빙된다. `http://localhost:3001/en/docs/...` 로 바로 접근 가능.
@@ -252,13 +245,15 @@ git push origin design
252245

253246
### 개요
254247

255-
`scripts/translate_to_en.py``docs/`·`blog/` 의 KR Markdown을 DeepL Free API로 번역해 `i18n/en/` 에 저장한다. `monthly-translate.yml`이 매월 1일 자동 실행한다.
248+
`scripts/translate_to_en.py``docs/`·`blog/` 의 KR Markdown을 DeepL Free API로 번역해 `i18n/en/` 에 저장한다. **`monthly-translate.yml`이 매월 1일 자동 실행**한다 (서버 crontab은 번역 미포함).
256249

257250
### 동작 방식
258251

259252
- **해시 캐시** (`.notion-translate-hashes.json`): SHA-256으로 변경된 파일만 번역. 미변경 파일 스킵.
260253
- **에러 격리**: 파일 하나 실패해도 나머지 계속 진행 (try-except per file).
261-
- `**<hr/>` 버그 방지**: DeepL이 `<hr/>` 앞뒤 줄바꿈을 제거하는 문제를 `\n\n---\n\n`으로 복원.
254+
- **`<hr/>` 버그 방지**: DeepL이 `<hr/>` 앞뒤 줄바꿈을 제거하는 문제를 `\n\n---\n\n`으로 복원.
255+
- **heading 공백 복원**: DeepL이 `###3.` 처럼 공백을 제거하는 경우 정규식으로 복원.
256+
- **blockquote 마커 복원**: DeepL이 `> ` 마커를 문장 중간으로 이동시키는 경우 복원.
262257
- **빌드 안전**: EN 번역 파일 없어도 Docusaurus는 KO fallback — 번역 실패가 배포 실패로 이어지지 않음.
263258

264259
### 수동 번역 실행
@@ -286,19 +281,25 @@ python3 scripts/translate_to_en.py
286281

287282
---
288283

289-
## 사이드바 ID ↔ Notion DB 매핑
284+
## navbar 자동 숨김 — `hasNotionContent`
290285

286+
`docusaurus.config.ts`에 빌드 타임 함수 `hasNotionContent(dirName)`가 있다. `docs/<dir>/` 안에 `placeholder.md``.md` 파일이 없으면 navbar 항목을 숨긴다.
291287

292-
| 사이드바 ID | `docs/` 경로 | 환경변수 | Notion 콘텐츠 유무 |
293-
| --------------------- | ---------------- | --------------------- | ------------------- |
294-
| `aboutSidebar` | `about/` | `NOTION_ABOUT` | ❌ placeholder.md 필요 |
295-
| `architectureSidebar` | `architecture/` | `NOTION_ARCHITECTURE` | ❌ placeholder.md 필요 |
296-
| `installSidebar` | `install/` | `NOTION_INSTALL` ||
297-
| `pocSidebar` | `poc/` | `NOTION_POC` ||
298-
| `docsSidebar` | `guide/` | `NOTION_DOCS` ||
299-
| `contributeSidebar` | `contribute/` | `NOTION_CONTRIBUTE` ||
300-
| `releaseNotesSidebar` | `release-notes/` | `NOTION_RELEASE` | ❌ placeholder.md 필요 |
288+
- Notion 콘텐츠가 없는 섹션: navbar에서 자동 제거 (빌드 시 평가)
289+
- Notion 콘텐츠 도착 → sync → `.md` 파일 생성 → 다음 빌드에서 자동 복원
290+
- `placeholder.md`는 사이드바 비어있음 빌드 에러 방지용 (Notion 콘텐츠가 없는 섹션에 필수)
301291

292+
## 사이드바 ID ↔ Notion DB 매핑
293+
294+
| 사이드바 ID | `docs/` 경로 | 환경변수 | Notion 콘텐츠 유무 |
295+
| --------------------- | ---------------- | --------------------- | ------------------------------- |
296+
| `aboutSidebar` | `about/` | `NOTION_ABOUT` | ❌ placeholder.md 필요 (navbar 숨김) |
297+
| `architectureSidebar` | `architecture/` | `NOTION_ARCHITECTURE` | ❌ placeholder.md 필요 (navbar 숨김) |
298+
| `installSidebar` | `install/` | `NOTION_INSTALL` ||
299+
| `pocSidebar` | `poc/` | `NOTION_POC` ||
300+
| `docsSidebar` | `guide/` | `NOTION_DOCS` ||
301+
| `contributeSidebar` | `contribute/` | `NOTION_CONTRIBUTE` ||
302+
| `releaseNotesSidebar` | `release-notes/` | `NOTION_RELEASE` | ❌ placeholder.md 필요 (navbar 숨김) |
302303

303304
블로그는 `sidebars.ts` 미포함 — navbar에 `{to: '/blog'}` 방식.
304305

@@ -313,22 +314,20 @@ HTML `<ol start="N">`이 자동 생성되어 코드블록으로 분리된 OL도
313314

314315
**카운터 리셋 기준 (`_OL_RESET_TYPES`):**
315316

316-
317317
| 블록 타입 | 동작 |
318318
| ----------------------------------------------------------- | ----------------------- |
319319
| `heading_1~4` | **리셋** (섹션 경계) |
320320
| `table`, `toggle`, `column_list` | **리셋** |
321321
| `code`, `paragraph`, `image`, `divider`, `quote`, `callout` | **유지** (split-OL 연속 번호) |
322322
| `bulleted_list_item`, `to_do` | **유지** |
323323

324-
325324
### HTML 엔티티 처리
326325

327326
Notion API가 `&gt;` 형태로 이중 인코딩할 때 `extract_text_from_rich_text`에서 안정될 때까지 반복 unescape.
328327

329328
### 꺾쇠 이스케이프 (`escape_mdx_angle_brackets`)
330329

331-
`<한글>` 패턴을 `<한글>`으로 변환해 MDX JSX 파싱 오류 방지. 코드 블록·인라인 코드 안은 건드리지 않는다.
330+
`<한글>` 패턴을 `\<한글>`으로 변환해 MDX JSX 파싱 오류 방지. 코드 블록·인라인 코드 안은 건드리지 않는다.
332331

333332
### child_page · link_to_page 블록
334333

@@ -343,7 +342,7 @@ Notion 인라인 서브페이지(`child_page`)와 페이지 링크(`link_to_page
343342
1. GitHub `secrets.NOTION_XXX` 등록 + `.env`에 추가
344343
2. `scripts/server-sync.sh`에 DB 동기화 블록 추가
345344
3. `docs/new-section/_category_.json` 생성
346-
4. `sidebars.ts` + `docusaurus.config.ts` navbar 추가
345+
4. `sidebars.ts` + `docusaurus.config.ts` navbar 추가 (hasNotionContent 조건부 포함)
347346
5. Notion DB에 콘텐츠가 없으면 `placeholder.md` 즉시 생성 (빌드 실패 방지)
348347

349348
**수동 Notion 동기화 (단일 섹션):**
@@ -384,4 +383,3 @@ with open('docs/poc/.notion-sync.json', 'w') as f:
384383
- 한 섹션 내 두 파일에 동일 slug 부여 금지 — 사이드바 이중 하이라이트 버그 발생
385384
- `i18n/en/` 파일 수동 편집 금지 — `translate_to_en.py` 실행 시 덮어씌워짐. EN 번역 수정은 스크립트 로직 수정으로.
386385
- `.notion-translate-hashes.json` 삭제·gitignore 금지 — 삭제 시 다음 CI 실행에서 전체 파일 재번역 (DeepL 한도 소진 위험)
387-

scripts/server-sync.sh

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ LOCKFILE="/tmp/docs-web-sync.lock"
1616
exec 200>"$LOCKFILE"
1717
flock -n 200 || { echo "[$(date)] 이미 다른 sync가 실행 중, 스킵"; exit 0; }
1818

19+
# 시작 브랜치 저장 — 스크립트 종료 시 복귀 (dev 서버 파일 보호)
20+
ORIG_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "")
21+
trap 'if [ -n "$ORIG_BRANCH" ] && [ "$ORIG_BRANCH" != "main" ]; then git checkout "$ORIG_BRANCH" --quiet 2>/dev/null || true; fi' EXIT
22+
1923
# 진행 중인 rebase 중단 (이전 실행 충돌로 잠긴 경우 해제)
2024
git rebase --abort 2>/dev/null || true
2125

@@ -83,17 +87,3 @@ if ! git diff --staged --quiet; then
8387
else
8488
echo "[$(date)] 동기화 완료 — 변경사항 없음"
8589
fi
86-
87-
# EN 번역 — 변경된 파일만 (hash cache로 미변경 스킵, DeepL quota 절약)
88-
if [ -n "$DEEPL_API_KEY" ]; then
89-
python3 scripts/translate_to_en.py || echo "[$(date)] WARN: 번역 중 오류 발생 (배포는 계속)"
90-
git add i18n/en/ .notion-translate-hashes.json
91-
if ! git diff --staged --quiet; then
92-
git -c user.name="server-cron" -c user.email="sbin@solbox.com" \
93-
commit -m "chore: EN 번역 자동 동기화 $(date +'%Y-%m-%d %H:%M')"
94-
git push origin main
95-
echo "[$(date)] EN 번역 완료 — 변경사항 push됨"
96-
else
97-
echo "[$(date)] EN 번역 완료 — 변경사항 없음"
98-
fi
99-
fi

0 commit comments

Comments
 (0)