Files
pipeline/.cursor/skills/notion-writing/SKILL.md
T
2026-03-12 18:47:42 +09:00

573 lines
17 KiB
Markdown

---
name: notion-writing
description: Notion MCP로 페이지를 작성할 때 반드시 따라야 하는 규칙. Notion 페이지 생성, 콘텐츠 작성, 문서화 요청 시 자동 적용.
---
# Notion 작성 규칙
## 저장 위치
모든 페이지는 WACE 페이지 하위에 생성한다.
```
WACE 페이지 ID: 31e2a200-9533-80ac-9fcf-d4ad3c676929
```
## MCP 서버 정보
- 서버명: `project-0-ERP-node-notion`
- 주요 API: `API-post-search`, `API-post-page`, `API-patch-block-children`, `API-retrieve-a-page`
## MCP 지원 블록 타입
`API-patch-block-children`은 다음 6가지 블록 타입을 지원한다.
| 블록 타입 | 용도 |
|-----------|------|
| `paragraph` | 일반 텍스트, 핵심 요약(📌), 경고(⚠), 빈 줄 |
| `heading_2` | 대섹션 제목 (## H2) |
| `heading_3` | 소제목 (### H3) |
| `divider` | 섹션 구분선 |
| `code` | 코드 블록, **Mermaid 다이어그램** |
| `bulleted_list_item` | 불릿 리스트 |
## 마크다운 문법 사용 금지
Notion API는 마크다운을 자동 변환하지 않는다. 텍스트에 마크다운을 넣으면 그대로 문자열로 표시된다.
금지:
- `## 제목` → 그대로 "## 제목"으로 표시됨
- `---` → 그대로 "---"로 표시됨
- `` ``` `` → 그대로 백틱 문자로 표시됨
- `> 인용` → 그대로 "> 인용"으로 표시됨
---
## 계층 페이지 생성 패턴
### 작업 순서 (필수)
1. `API-post-search`로 대상 페이지/데이터베이스 검색
2. 검색 결과에서 `object` 필드로 `page`인지 `database`인지 구분
3. `API-post-page`로 상위 페이지 생성 (반환된 ID 기록)
4. 생성된 페이지 ID를 parent로 하위 페이지 생성
5. `API-patch-block-children`으로 각 페이지에 콘텐츠 추가
### 검색 (API-post-search)
```json
{
"query": "검색할 제목",
"page_size": 10
}
```
검색 결과에서 `object` 필드 확인:
- `"object": "page"` → page_id parent 사용
- `"object": "database"` → database_id parent 사용
### 데이터베이스(피드보기) 하위에 페이지 생성
DB의 title 속성명을 키로 사용한다 (보통 `"이름"`).
```json
{
"parent": {"database_id": "<DB-ID>"},
"properties": {"이름": {"title": [{"text": {"content": "페이지 제목"}}]}},
"icon": "{\"type\": \"emoji\", \"emoji\": \"📘\"}"
}
```
### 페이지 하위에 서브 페이지 생성
properties 키는 `"title"`을 사용한다 (DB 하위와 다름에 주의).
```json
{
"parent": {"page_id": "<PAGE-ID>"},
"properties": {"title": {"title": [{"text": {"content": "서브 페이지 제목"}}]}},
"icon": "{\"type\": \"emoji\", \"emoji\": \"📦\"}"
}
```
### parent 유형별 차이 요약
| 대상 | parent | properties 키 | 예시 |
|------|--------|---------------|------|
| DB 하위 | `{"database_id": "..."}` | DB의 title 속성명 (예: `"이름"`) | `{"이름": {"title": [...]}}` |
| 페이지 하위 | `{"page_id": "..."}` | `"title"` (고정) | `{"title": {"title": [...]}}` |
| WACE 직접 하위 | `{"page_id": "31e2a200-9533-80ac-9fcf-d4ad3c676929"}` | `"title"` | `{"title": {"title": [...]}}` |
### icon 설정
icon은 반드시 **JSON 문자열**로 전달한다 (객체가 아님):
```
"{\"type\": \"emoji\", \"emoji\": \"📘\"}"
```
---
## 코드 블록 language 목록
Notion API가 지원하는 주요 language 값. 지원하지 않는 값을 넣으면 **400 에러** 발생.
| language | 용도 | 비고 |
|----------|------|------|
| `shell` | 터미널 명령어 실행 | |
| `bash` | Shell 스크립트 파일 내용 | |
| `docker` | Dockerfile 내용 | `dockerfile`은 미지원 |
| `yaml` | docker-compose.yml, CI/CD 워크플로우 | |
| `json` | JSON 설정 파일 | |
| `javascript` | JS 코드 | |
| `typescript` | TS 코드 | |
| `python` | Python 코드 | |
| `sql` | SQL 쿼리 | |
| `html` | HTML 마크업 | |
| `css` | CSS 스타일 | |
| `hcl` | Terraform 설정 | |
| `mermaid` | 다이어그램 (Notion이 자동 시각화) | |
| `plain text` | 일반 텍스트 | |
코드 블록 JSON 예시:
```json
{"type": "code", "code": {"rich_text": [{"type": "text", "text": {"content": "docker-compose up -d\ndocker-compose ps"}}], "language": "shell"}}
```
### 코드 블록 작성 규칙
- 코드 블록 앞에 `bulleted_list_item`으로 **작업명** 라벨 배치
- 코드 블록 뒤에 `paragraph`로 부가 설명 추가 (code annotation으로 명령어 강조)
- 코드 블록 내 `#` 주석으로 각 명령어 설명 가능
- 명령어 실행: `language: "shell"` / 스크립트 파일: `language: "bash"` 구분
---
## 제목 계층 구조 (필수)
원본 문서의 #/##/### 제목 계층을 반드시 Notion 네이티브 블록으로 변환한다.
### H2 (대섹션 제목)
`heading_2` 블록을 사용한다. 앞에 `divider`를 넣어 시각적으로 구분한다.
```json
{"type": "divider", "divider": {}}
{"type": "heading_2", "heading_2": {"rich_text": [{"type": "text", "text": {"content": "🔹 대섹션 제목"}}]}}
```
### H3 (소제목)
`heading_3` 블록을 사용한다. divider 없이 바로 사용.
```json
{"type": "heading_3", "heading_3": {"rich_text": [{"type": "text", "text": {"content": "1️⃣ 소제목"}}]}}
```
### 결론/완료 기준 섹션
```json
{"type": "divider", "divider": {}}
{"type": "heading_2", "heading_2": {"rich_text": [{"type": "text", "text": {"content": "✅ 완료 기준"}}]}}
```
## Mermaid 다이어그램 (필수 — 적극 활용)
다이어그램은 반드시 `code` 블록 + `language: "mermaid"`로 작성한다.
Notion은 Mermaid 코드 블록을 자동으로 시각화 렌더링한다.
### code 블록 사용법
```json
{"type": "code", "code": {"rich_text": [{"type": "text", "text": {"content": "graph TD\n A[시작] --> B[처리]\n B --> C[완료]"}}], "language": "mermaid"}}
```
### 다이어그램 유형별 Mermaid 코드
**시퀀스 다이어그램 (API 호출 흐름):**
```mermaid
sequenceDiagram
participant U as 사용자
participant V as v2-report-viewer
participant B as Backend API
participant D as PostgreSQL
U->>V: 1. 메뉴 진입
V->>B: 2. 매핑 리포트 조회
B->>D: 3. report_menu_mapping 조회
D-->>B: 4. 리포트 목록
B-->>V: 5. 리포트 목록 반환
U->>V: 6. 리포트 선택
V->>B: 7. 데이터 + 레이아웃 요청
B->>D: 8. report_master + 쿼리 실행
D-->>B: 9. 결과 반환
B-->>V: 10. 렌더링 데이터
V-->>U: 11. PDF/미리보기
```
**플로우 다이어그램 (업무 프로세스):**
```mermaid
graph LR
A[거래처관리] --> B[견적관리]
B --> C[수주관리]
C --> D[생산계획]
D --> E[작업지시]
E --> F[POP실적]
F --> G[입고]
G --> H[출고]
H --> I[세금계산서]
C --> J[발주관리]
J --> K[입고관리]
K --> L[품질검사]
L --> G
```
**아키텍처 다이어그램 (시스템 구조):**
```mermaid
graph TD
subgraph Frontend
A[업무 화면] --> B[v2-report-viewer]
end
subgraph Backend
C[reportController] --> D[reportService]
end
subgraph Database
E[report_master]
F[report_menu_mapping]
end
B -->|API 호출| C
D -->|쿼리| E
D -->|쿼리| F
```
**ER 다이어그램 (DB 구조):**
```mermaid
erDiagram
report_master ||--o{ report_menu_mapping : "1:N"
report_master {
int report_id PK
string report_name
text query_text
jsonb layout_json
string company_code
}
report_menu_mapping {
int id PK
int report_id FK
int menu_objid FK
int sort_order
string company_code
}
```
**상태 다이어그램:**
```mermaid
stateDiagram-v2
[*] --> 초안
초안 --> 검토중
검토중 --> 승인
검토중 --> 반려
반려 --> 수정
수정 --> 검토중
승인 --> 활성
활성 --> 비활성
초안 --> 삭제
```
### 다이어그램 삽입 시점 (적극 활용)
| 설명 내용 | 다이어그램 유형 | Mermaid 타입 |
|-----------|----------------|-------------|
| 시스템 아키텍처 | 아키텍처 다이어그램 | `graph TD` + `subgraph` |
| API 호출 흐름 | 시퀀스 다이어그램 | `sequenceDiagram` |
| 업무 프로세스 | 플로우 다이어그램 | `graph LR` 또는 `graph TD` |
| DB 구조 | ER 다이어그램 | `erDiagram` |
| 상태 변화 | 상태 다이어그램 | `stateDiagram-v2` |
---
## 올바른 서식 적용 방법
### 핵심 요약 (📌)
대섹션 시작 직후 paragraph로 핵심 개념을 요약한다.
```json
{"type": "paragraph", "paragraph": {"rich_text": [
{"type": "text", "text": {"content": "📌 "}, "annotations": {"bold": true}},
{"type": "text", "text": {"content": "리포트 시스템"}, "annotations": {"bold": true, "italic": true}},
{"type": "text", "text": {"content": "은 모든 단계에 걸쳐 있는 "}, "annotations": {"bold": true}},
{"type": "text", "text": {"content": "횡단 출력 레이어"}, "annotations": {"bold": true, "italic": true}},
{"type": "text", "text": {"content": "이다."}, "annotations": {"bold": true}}
]}}
```
### 경고/안내 텍스트 (⚠)
주의사항이나 미완성 안내에 사용한다.
```json
{"type": "paragraph", "paragraph": {"rich_text": [
{"type": "text", "text": {"content": "⚠ 절대 main/develop에 push 금지. 개인 브랜치에서만 작업할 것"}, "annotations": {"bold": true}}
]}}
```
### 강조 텍스트
```json
{"type": "text", "text": {"content": "강조할 텍스트"}, "annotations": {"bold": true}}
```
### 인라인 코드
```json
{"type": "text", "text": {"content": "report_master"}, "annotations": {"code": true}}
```
### 불릿 리스트
```json
{"type": "bulleted_list_item", "bulleted_list_item": {"rich_text": [
{"type": "text", "text": {"content": "항목 이름"}, "annotations": {"bold": true}},
{"type": "text", "text": {"content": " — 설명 텍스트"}}
]}}
```
### 불릿 + 인라인 코드 조합
명령어/URL을 검증 항목으로 나열할 때 사용한다.
```json
{"type": "bulleted_list_item", "bulleted_list_item": {"rich_text": [
{"type": "text", "text": {"content": "docker-compose up -d"}, "annotations": {"code": true}},
{"type": "text", "text": {"content": " 한 번으로 전체 스택 기동 성공"}}
]}}
```
### 빈 줄
```json
{"type": "paragraph", "paragraph": {"rich_text": []}}
```
### 구분선
```json
{"type": "divider", "divider": {}}
```
## 사용 가능한 annotations
| annotation | 용도 |
|---|---|
| `bold: true` | 제목, 라벨, 강조, 경고 |
| `italic: true` | 부가 설명 |
| `bold: true` + `italic: true` | 핵심 기술 용어 첫 등장 |
| `code: true` | 파일 경로, 명령어, 인라인 코드 |
| `bold: true` + `code: true` | 코드 강조 (예: pg_dump 라벨) |
| `strikethrough: true` | 취소선 |
| `underline: true` | 밑줄 |
---
## 페이지 생성 절차
### 단일 페이지 (WACE 직접 하위)
1. `API-post-page`로 빈 페이지 생성 (WACE 하위)
2. `API-patch-block-children`으로 콘텐츠 추가
3. 한 번에 최대 100블록까지 추가 가능, 초과 시 나눠서 호출
### 계층 페이지 (DB/페이지 하위 트리)
1. `API-post-search`로 대상 페이지/DB 검색 → ID 확인
2. `API-post-page`로 상위 페이지 생성 (DB 또는 페이지 하위) → ID 기록
3. 생성된 ID를 parent로 하위 페이지 생성 → ID 기록
4. 각 페이지에 `API-patch-block-children`으로 콘텐츠 추가
5. 콘텐츠가 많으면 여러 번 나눠서 호출 (100블록 제한)
병렬 생성 가능: 같은 레벨의 페이지는 동시에 생성할 수 있다.
순차 생성 필수: 상위 페이지 ID가 있어야 하위 페이지를 생성할 수 있다.
---
## 페이지 구조 템플릿
### 기본 문서 페이지
```
paragraph: 📌 핵심 요약 (bold, 기술용어 bold+italic)
divider
heading_2: 🔹 대섹션 제목 1
paragraph: 📌 핵심 요약 (bold, 기술용어 bold+italic)
heading_3: 1️⃣ 소제목 1
bulleted_list_item: **키워드** — 설명
bulleted_list_item: **키워드** — 설명
code (mermaid): 시퀀스/플로우/아키텍처/ER 다이어그램
heading_3: 2️⃣ 소제목 2
paragraph: 설명 텍스트
bulleted_list_item: 항목들
divider
heading_2: 🔹 대섹션 제목 2
...
divider
heading_2: ✅ 결론
bulleted_list_item: 결론 1
bulleted_list_item: 결론 2
```
### Phase(개요) 페이지
로드맵, 프로젝트 계획 등 상위 개요 페이지에 사용한다.
```
paragraph: 📌 Phase 핵심 요약 (bold, 기술용어 bold+italic)
(빈 줄)
divider
heading_2: 🔹 Phase 개요
bulleted_list_item: **기간** — 날짜 범위
bulleted_list_item: **학습 도구** — 도구 목록
bulleted_list_item: **목표** — 목표 설명
(빈 줄)
divider
heading_2: 🔹 Sprint 목록 (또는 작업 목록)
bulleted_list_item: **S0N (날짜)** — Sprint 설명
bulleted_list_item: **S0N (날짜)** — Sprint 설명
bulleted_list_item: **S0N (날짜)** — Sprint 설명
(빈 줄)
divider
heading_2: ✅ 완료 기준
bulleted_list_item: 검증 항목 (`코드/명령어` 인라인 코드 포함)
bulleted_list_item: 검증 항목
```
### Sprint(실습) 페이지
기술 학습, 실습 가이드, 단계별 튜토리얼에 사용한다.
```
paragraph: 📌 Sprint 핵심 요약 (bold, 기술용어 bold+italic)
(빈 줄)
divider
heading_2: 🔹 1단계: 단계 제목
paragraph: 📌 이 단계의 목적 (bold)
(빈 줄)
bulleted_list_item: **작업명** (bold)
code (shell): 실행할 명령어
(빈 줄)
bulleted_list_item: **다음 작업명** (bold)
code (shell/bash/yaml/docker): 파일 내용 또는 명령어
paragraph: 부가 설명 (`명령어` code annotation 강조)
(빈 줄)
divider
heading_2: 🔹 2단계: 단계 제목
paragraph: 📌 이 단계의 목적 (bold)
(빈 줄)
bulleted_list_item: **작업명** (bold)
code (language): 코드/명령어
(빈 줄)
bulleted_list_item: **핵심 개념** (bold)
bulleted_list_item: `키워드` — 설명 (code + 일반 텍스트)
bulleted_list_item: `키워드` — 설명
(빈 줄)
... (단계 반복)
divider
heading_2: ✅ 완료 기준
bulleted_list_item: `명령어/URL` 검증 항목 (code annotation)
bulleted_list_item: 검증 항목
```
### 간략 페이지 (미래 작업용)
아직 상세 내용이 없는 페이지에 사용한다.
```
paragraph: 📌 핵심 요약 한 줄 (bold)
(빈 줄)
paragraph: ⚠ 상세 실습 콘텐츠는 해당 Phase 진입 시 추가 예정 (bold)
```
---
## 텍스트 서식 규칙
| 용도 | 서식 | 예시 |
|------|------|------|
| 핵심 기술 용어 (첫 등장) | bold + italic | ***Docker***, ***Terraform*** |
| 핵심 개념/키워드 | bold | **레이어 캐싱**, **멀티스테이지 빌드** |
| 코드/명령어/경로/URL | code annotation | `docker-compose up -d`, `/api/health` |
| 코드 + 강조 | bold + code | **`pg_dump`** |
| 부가 설명 | 일반 텍스트 (괄호) | (만료 전까지 사용 가능) |
| 경고/주의 | ⚠ + bold | **⚠ 절대 main에 push 금지** |
## 이모지 사용 규칙
| 이모지 | 용도 |
|--------|------|
| ✅ | 완료 기준 섹션, 장점, 완료 상태 |
| 🔹 | 대섹션 제목 (heading_2), 단계 제목 |
| 📌 | 핵심 요약, 단계 목적 설명 |
| ⚠ | 경고, 주의사항, 미완성 안내 |
| 1️⃣2️⃣3️⃣ | 소제목 번호 (heading_3) |
| 🧩🔗 | 개념 설명 소제목 |
| 📦📝⚙️🏗️🔧🚀📚🌐🔥📊📈🎯 | Sprint/페이지 icon |
---
## 체크리스트
Notion 콘텐츠 작성 전 확인:
**계층 페이지 생성:**
- API-post-search로 대상 페이지/DB를 먼저 검색했는가
- 검색 결과의 object 필드로 page/database를 구분했는가
- DB 하위 페이지는 `database_id` parent + DB의 title 속성명(예: "이름")을 사용했는가
- 페이지 하위 페이지는 `page_id` parent + `"title"` 속성명을 사용했는가
- 생성된 페이지 ID를 기록하여 하위 페이지/콘텐츠 추가에 사용했는가
- icon을 JSON 문자열 형식으로 전달했는가
**제목 계층 구조 (필수):**
- heading_2 블록으로 대섹션(H2)을 만들었는가
- heading_3 블록으로 소제목(H3)을 만들었는가
- divider 블록으로 대섹션 사이를 구분했는가
- 원본 문서의 #/##/### 계층이 heading_2/heading_3으로 정확히 반영되었는가
**코드 블록:**
- language 값이 Notion API 지원 목록에 있는가 (`dockerfile``docker`)
- 코드 블록 앞에 bulleted_list_item으로 라벨을 배치했는가
- 코드 블록 내 주석(#)으로 각 명령어를 설명했는가
- 명령어 실행은 `shell`, 스크립트 파일은 `bash`로 구분했는가
**Mermaid 다이어그램 (필수):**
- 시스템 아키텍처 → code 블록 + mermaid (graph TD + subgraph)
- API 호출 흐름 → code 블록 + mermaid (sequenceDiagram)
- 업무 프로세스 → code 블록 + mermaid (graph LR)
- DB 구조 → code 블록 + mermaid (erDiagram)
- 상태 변화 → code 블록 + mermaid (stateDiagram-v2)
- code 블록의 language가 "mermaid"로 설정되었는가
**마크다운 금지:**
- 텍스트에 `##`, `###` 마크다운 헤딩을 넣지 않았는가
- 텍스트에 `---` 마크다운 구분선을 넣지 않았는가
- annotations에 code: true를 넣고 텍스트에도 백틱을 넣지 않았는가
**서식 규칙:**
- 이모지 접두사를 적절히 사용했는가 (✅, 🔹, 📌, ⚠ 등)
- 핵심 기술 용어 첫 등장 시 bold + italic 조합을 사용했는가
- 불릿 리스트에서 "**키워드** — 설명" 패턴을 따랐는가
- 경고/안내 텍스트에 ⚠ + bold를 사용했는가