# 헬프 센터를 git으로 관리하기

도움말 글을 저장소에 Markdown으로 두고, 코드처럼 풀 리퀘스트에서 검토할 수 있습니다. 머지할 때마다 CI가 글을 헬프 센터에 푸시합니다. 새 페이지는 만들어지고, 바뀐 페이지는 새 리비전이 생겨 게시되며, 나머지는 그대로 둡니다. 번역, 검색, 피드백, 공개 사이트는 Mocco에서 쓴 글과 똑같이 동작하고, 번역도 git에 둘 수 있습니다. Mocco의 가이드도 이 방식으로 게시됩니다.

## 1. 폴더 구성하기

섹션별로 페이지를 폴더에 두고, 이미지는 그 옆의 `images/`에 둡니다.

```
docs/help/
  help.json
  glossary.csv          (optional)
  start/
    overview.md
    install.md
    images/
      home.png
  billing/
    plans.md
```

각 페이지는 `title`이 있는 프론트매터로 시작합니다. 페이지에 `# Title` 줄이 있으면 버려집니다. 사이트가 제목을 페이지 제목으로 보여 주기 때문입니다.

```markdown
---
title: Install the app
---

# Install the app

Download it from the [overview](./overview.md#download).

![The home screen after installing](./images/home.png)
```

페이지 사이의 링크는 `./page.md` 또는 `../folder/page.md`이며, `#anchor`를 붙일 수 있습니다. 사이트에서는 독자의 언어로 된 해당 글로 연결됩니다. 이미지는 `./images/<name>`입니다(PNG, JPEG, WebP, GIF, 최대 10 MB). 그 밖의 상대 링크는 푸시를 실패시키므로, 오타는 독자에게 닿기 전에 잡힙니다.

## 2. 매니페스트 작성하기

`help.json`은 각 폴더가 어디에 어떤 순서로 나타날지 정합니다.

```json
{
  "collections": [
    {
      "slug": "guides",
      "title": "Guides",
      "sections": [
        { "folder": "start", "title": "Getting started", "pages": ["overview", "install"] },
        { "folder": "billing", "title": "Billing", "pages": ["plans"] }
      ]
    }
  ]
}
```

매니페스트에 없는 페이지는 나열된 페이지 뒤에 알파벳순으로 붙습니다. 매니페스트에 없는 폴더가 있으면 푸시가 실패합니다.

## 3. 키 만들기

프로젝트의 **API keys** 페이지에서 `help:write` 스코프만 가진 **secret** 키를 만듭니다. `MOCCO_API_KEY` 같은 이름의 CI 시크릿으로 저장하세요. 프로젝트에 헬프 센터가 먼저 설정되어 있어야 합니다.

## 4. CI에서 푸시하기

```yaml
name: Help center
on:
  push:
    branches: [main]
    paths: ['docs/help/**']
jobs:
  push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - run: npx @mocco/cli help push docs/help --glossary docs/help/glossary.csv --prune
        env:
          MOCCO_API_KEY: ${{ secrets.MOCCO_API_KEY }}
```

사용하는 액션과 CLI 버전은 고정하세요. 명령은 수행한 일을 출력합니다.

```
12 page(s), 30 image(s), 8 glossary term(s).
Images: 2 uploaded, 28 already stored.
Glossary: 0 added, 1 changed, 7 unchanged.
Articles: 0 created, 3 updated, 9 unchanged; 3 published, 0 unpublished.
```

이미지는 먼저 체크섬으로 확인하므로, 푸시할 때 새 이미지만 업로드됩니다.

- `--dry-run`은 모든 페이지, 링크, 이미지를 검사하고 아무것도 보내지 않습니다. 키가 필요 없으므로 풀 리퀘스트에서 실행하세요.
- `--prune`은 전에 푸시했지만 이제 폴더에 없는 페이지를 게시 취소합니다. 그 페이지의 기록과 번역은 남고, 페이지가 돌아오면 다시 게시됩니다. Mocco에서 쓴 글은 건드리지 않습니다. 파일을 지운 번역도 기계에 돌려줍니다([번역](#5-translations) 참고).
- `--no-publish`는 새 페이지와 바뀐 페이지를 초안으로 남겨 두어 Mocco에서 게시할 수 있게 합니다.
- `--glossary`는 CSV에서 용어집 용어를 추가하거나 갱신합니다. 형식은 Glossary 페이지의 **Import CSV**와 같습니다. 파일에 없는 용어는 그대로 남습니다.

폴더 안의 각 페이지 경로(`/start/install`)는 글로 리디렉션되는 주소로 사이트에 유지됩니다. 페이지의 파일 이름을 바꾸면 새 글이 되고, `--prune`을 쓰면 이전 글은 게시 취소됩니다.

## 5. 번역

헬프 센터가 다른 언어를 제공하면 모든 페이지가 번역됩니다. 텍스트를 git에서 가져올지 기계에서 가져올지는 페이지와 언어마다 정합니다.

- **git의 파일은 그대로 사용됩니다.** 같은 docs 폴더에 `<locale>/<folder>/<page>.md`로, 원문 페이지와 같은 경로에 번역을 두면 푸시가 그것을 검수된 텍스트로 저장합니다. 기계가 이를 덮어쓰지 않습니다.
- **파일이 없어도 괜찮습니다.** 어떤 언어의 파일이 없는 페이지는 Mocco가 번역하며, 그 텍스트는 나중에 git에서 고칠 수 있습니다.

```
docs/help/
  help.json
  start/
    overview.md
    images/
      home.png
  ko/
    start/
      overview.md
```

번역 파일의 프론트매터는 원문과 같습니다(`title`, 그다음 본문). 이미지는 `./images/<name>`으로, 링크는 `./page.md`로 원문과 똑같이 씁니다. 이 경로는 원문 폴더의 이미지와 페이지를 가리키며, 로케일 폴더에는 이미지를 두지 않습니다. 원문 페이지가 없는 파일은 푸시를 실패시키고, 헬프 센터가 제공하지 않는 언어의 폴더도 마찬가지입니다.

`help.json`에 없는 최상위 폴더는 언어로 읽습니다. 따라서 섹션 이름을 언어 코드처럼 짓지 마세요.

### 푸시가 번역을 처리하는 방식

| git의 상태 | 푸시가 하는 일 |
| --- | --- |
| 새 텍스트가 있는 파일 | 지금 푸시하는 원문에 대한 검수된 번역으로 저장하고, 그 옆의 기계 초안을 버립니다 |
| 같은 텍스트가 있는 파일 | 그대로 둡니다 |
| 파일이 있지만, 이번 푸시에서 원문만 바뀌고 파일은 바뀌지 않음 | 파일의 텍스트를 계속 제공하고, 오래된 것으로 표시하며, 그 옆에 기계 제안을 초안으로 만듭니다 |
| 파일이 없고, 그 페이지가 git 번역이었던 적이 없음 | 기계가 전과 같이 번역합니다 |
| 파일이 없지만, 그 페이지에 git 번역이 있었음 | 계속 제공하고 사라졌다고 보고합니다. `--prune`을 쓰면 페이지가 기계로 돌아가 다시 번역됩니다 |

원문과 같은 커밋에서 수정한 번역은 그 원문에 대한 답으로 봅니다. 손대지 않은 번역은 그렇게 보지 않으며, 푸시는 이것으로 번역이 오래되었음을 압니다. 명령은 언어마다 한 줄씩 출력합니다. `--prune`이 페이지를 게시 취소했다면 줄 끝에 `; unpublished`와 그 경로가 붙습니다. `--prune` 없이 푸시했는데 파일이 사라진 git 번역이 있으면 줄 끝에 `; gone`, 그 경로, 번역이 유지된다는 안내가 붙습니다.

```
ko: saved 3, unchanged 9, stale 1 (/start/install), handed back 0.
ko: saved 0, unchanged 12, stale 0, handed back 0; gone /start/keys (kept; push with --prune to hand them back to the machine).
```

번역이 원문을 따라가도록 CI에서 강제하고 싶다면 `--fail-on-stale`을 추가하세요. 오래된 번역이 하나라도 있으면 가져오기를 마친 뒤 푸시가 오류로 종료됩니다. 이 옵션이 없으면 오래된 페이지는 마지막으로 검수된 텍스트를 유지하고 보고서에 나열됩니다. `--dry-run`은 모든 번역 파일을 검사하고, 언어마다 어떤 페이지에 파일이 있는지 나열합니다.

### 기계의 텍스트를 git으로 가져오기

기계 번역을 풀 리퀘스트에서 고치려면 먼저 폴더로 가져옵니다.

```bash
npx @mocco/cli help pull docs/help --locale ko
```

푸시와 마찬가지로 `help:write`가 있는 **secret** 키가 필요합니다. 게시 취소된 텍스트와 기계 초안은 공개되지 않기 때문입니다. 해당 언어의 파일이 없는 모든 페이지에 대해 파일을 쓰고 그 수를 보고합니다.

```
ko: 12 written, 0 already there.
```

1. 언어를 가져옵니다.
2. 풀 리퀘스트에서 파일을 고칩니다.
3. 머지합니다. 다음 푸시가 바뀐 파일을 검수된 번역으로 저장하고, 그때부터 그 파일들은 git 번역이 됩니다.

기계가 아직 끝내지 못했거나 시작하지 않은 페이지(방금 추가한 페이지)는 나중에 다시 가져올 수 있도록 목록에 나옵니다. 두 플래그로 쓰는 내용을 바꿀 수 있습니다.

- `--overwrite`는 이미 있는 파일도 교체합니다. 사이트의 현재 텍스트를 가져오거나 잘못된 수정에서 복구할 때 씁니다.
- `--proposals`는 오래된 번역에 대해 제공 중인 텍스트 대신 기계의 제안을 쓰고, `--overwrite` 없이도 그 파일을 교체합니다. 그래서 수정이 새 원문의 초안에서 출발합니다. 이미 있는 다른 파일은 그대로 남습니다.

가져온 뒤 수정 없이 푸시하면 아무것도 바뀌지 않습니다.

## 6. 콘솔에서 달라지는 점

첫 푸시는 헬프 센터를 **managed in git**으로 표시합니다. git이 유일한 원본으로 남아야 하기 때문입니다. 이를 원하지 않으면 `--no-manage`로 푸시하고, 폴더가 있는 위치를 기록하려면 `--source <url>`을 쓰세요(이후 푸시에서 생략하면 저장된 값이 유지됩니다).

![git으로 관리된다는 배너와 저장소 링크가 있는 Help center 페이지](https://fi-workers-mocco-storage.s3.ap-northeast-2.amazonaws.com/pub/w/93e11fe8-0494-4e3d-b1cb-fe4dffd3ee7e/p/d64785b8-9a23-4fa1-a81d-550af30e203a/helpcenter/8e17c002-c107-4a76-815a-63757a0e7956/managed-in-git-banner.png)

git으로 관리되는 헬프 센터에서는 다음과 같습니다.

- 배너에 저장소가 표시되고 편집 컨트롤이 사라집니다. 글, 컬렉션, 섹션, 번역, 용어집을 콘솔, [MCP](https://www.mocco.club/docs/ko/articles/frhj3w-connect), API로 바꿀 수 없습니다. 푸시만 바꿀 수 있으므로, 누군가 따로 한 수정을 덮어쓰는 일이 생기지 않습니다.
- 사이트 설정은 계속 편집할 수 있습니다. 언어, 주소, AI 학습, 피드백입니다. 언어를 추가하면 모든 글이 기계로 그 언어에 번역됩니다.
- **Translations** 페이지는 각 번역의 출처를 보여 줍니다. 푸시한 파일은 **Git**, 헬프 센터가 관리되기 전에 누군가 콘솔에서 쓴 텍스트는 **Person**, Mocco의 번역은 **Machine**입니다. 원문이 바뀐 git 번역에는 **Stale — proposal ready**라고 표시됩니다.

![Git, Person, Machine 배지와 오래된 한국어 번역이 있는 번역 대시보드](https://fi-workers-mocco-storage.s3.ap-northeast-2.amazonaws.com/pub/w/93e11fe8-0494-4e3d-b1cb-fe4dffd3ee7e/p/d64785b8-9a23-4fa1-a81d-550af30e203a/helpcenter/033e6707-f848-40d6-a600-2b7859d9d22c/translations-origin-badges.png)

### git에서 헬프 센터 해제하기

소유자나 관리자는 헬프 센터를 콘솔로 돌려줄 수 있습니다. **Help center**를 열고 **Release from git**을 선택한 다음 확인하세요. 콘텐츠는 그대로 남으며, 에이전트는 `mocco_help_site_release` 도구로 같은 일을 할 수 있습니다.

![Release from git 확인: 해제한 뒤 콘솔에서 한 수정은 다음 푸시가 교체합니다](https://fi-workers-mocco-storage.s3.ap-northeast-2.amazonaws.com/pub/w/93e11fe8-0494-4e3d-b1cb-fe4dffd3ee7e/p/d64785b8-9a23-4fa1-a81d-550af30e203a/helpcenter/e01b8696-4989-48d3-b1d7-37be9663c3e0/release-from-git-confirm.png)

푸시는 헬프 센터를 다시 가져가므로, 해제한 뒤 콘솔에서 한 수정은 다음 푸시가 교체합니다. 해제는 저장소를 옮기는 동안처럼 비상시에 쓰는 수단이며, 일상적인 작업 방식이 아닙니다.
