feat: initial CTStruct framework

- CTNode: 트리 기본 단위 (전위/후위/BFS 순회, 탐색, 분리)
- CTTree: 트리 컨테이너 (빌더 API, TOC, filter/map/merge)
- NodeType: 구조/블록/인라인/메타 노드 타입 Enum
- MarkdownParser: Markdown → CTTree 파서
- MarkdownRenderer: CTTree → Markdown 렌더러
- JSONRenderer: CTTree → JSON 직렬화
- 27개 단위/통합 테스트 전체 통과
This commit is contained in:
2026-05-30 20:40:28 +09:00
commit 6e3cd19b55
38 changed files with 1695 additions and 0 deletions

243
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,243 @@
# CTStruct 아키텍처 문서
## 1. 개요
CTStruct(Contextual Text Structure)는 다양한 텍스트 포맷을 **단일 트리 자료구조**로 표현하고,
파서와 렌더러를 플러그인처럼 교체할 수 있도록 설계된 Python 라이브러리입니다.
---
## 2. 설계 목표
| 목표 | 설명 |
|------|------|
| **통일성** | Markdown, JSON, 일반 텍스트 등 모든 포맷이 동일한 CTTree API로 조작됨 |
| **확장성** | 새 파서·렌더러를 `BaseParser` / `BaseRenderer` 상속으로 추가 가능 |
| **불변 변환** | `filter()`, `map()` 은 원본 트리를 변경하지 않고 새 트리 반환 |
| **의존성 최소화** | 표준 라이브러리만 사용, 외부 패키지 없음 |
| **타입 안전성** | `NodeType` Enum 으로 잘못된 타입 사용 방지 |
---
## 3. 핵심 구성요소
### 3.1 NodeType (types.py)
```
NodeType
├── 구조 노드: ROOT, DOCUMENT, SECTION
├── 블록 노드: HEADING, PARAGRAPH, LIST, LIST_ITEM,
│ TABLE, TABLE_ROW, TABLE_CELL,
│ CODE_BLOCK, BLOCKQUOTE, DIVIDER
├── 인라인 노드: TEXT, BOLD, ITALIC, CODE, LINK, IMAGE
└── 메타 노드: METADATA, ANNOTATION, CUSTOM
```
`NodeType` 은 Python `Enum` 으로 구현되어 있으며,
노드의 **의미적 역할**을 정의합니다.
---
### 3.2 CTNode (node.py)
트리의 기본 단위. `dataclass` 로 구현되어 있습니다.
```
CTNode
├── node_id : str # 고유 식별자 (8자리 hex)
├── node_type : NodeType # 의미적 타입
├── content : str | None # 직접 보유 텍스트
├── attributes : dict # 메타정보 (level, lang, …)
├── parent : CTNode | None
└── children : list[CTNode]
```
#### 주요 메서드
| 메서드 | 설명 |
|--------|------|
| `append(child)` | 자식 추가 (체이닝 지원) |
| `prepend(child)` | 맨 앞 삽입 |
| `insert(i, child)` | 지정 위치 삽입 |
| `remove(child)` | 자식 제거 |
| `detach()` | 부모에서 자신을 분리 |
| `walk(order)` | `"pre"` / `"post"` / `"bfs"` 순회 |
| `find(type)` | 타입별 하위 노드 검색 |
| `ancestors()` | 부모 방향 이터레이터 |
| `text_content()` | 모든 하위 텍스트 추출 |
| `pretty()` | 트리 시각화 문자열 |
---
### 3.3 CTTree (tree.py)
루트 노드를 감싸는 컨테이너. 문서 단위의 고수준 API를 제공합니다.
```
CTTree
└── root: CTNode (NodeType.ROOT)
```
#### 빌더 API (정적 메서드)
```python
CTTree.make_heading(text, level)
CTTree.make_paragraph(text)
CTTree.make_code_block(code, language)
CTTree.make_list(items, ordered)
CTTree.make_table(headers, rows)
```
#### 탐색 API
```python
tree.find(NodeType.HEADING) # 타입별 검색
tree.find_by_id("a1b2c3d4") # ID 검색
tree.headings() # 헤딩 목록
tree.toc() # 목차 생성
tree.walk(order) # 전체 순회
```
#### 변환 API (원본 불변)
```python
tree.filter(predicate) # 조건 필터링 → 새 CTTree
tree.map(transform) # 변환 적용 → 새 CTTree
tree.merge(other) # 다른 트리 병합 (in-place)
```
#### 직렬화
```python
d = tree.to_dict() # Python dict
tree = CTTree.from_dict(d) # dict → CTTree
```
---
### 3.4 파서 (parsers/)
```
BaseParser (추상)
└── parse(text: str) → CTTree
└── MarkdownParser
├── frontmatter 파싱 (--- key: value ---)
├── ATX 헤딩 (# ~ ######)
├── 섹션 자동 분류 (H1 기준)
├── 코드 블록 (``` … ```)
├── 목록 (-, *, 1.)
├── 인용구 (>)
├── 구분선 (---)
└── 문단 (multi-line 연결)
```
**커스텀 파서 작성:**
```python
from ctstruct.parsers import BaseParser
from ctstruct import CTTree, CTNode, NodeType
class MyParser(BaseParser):
def parse(self, text: str) -> CTTree:
tree = CTTree()
for line in text.splitlines():
tree.add(NodeType.PARAGRAPH, line)
return tree
```
---
### 3.5 렌더러 (renderers/)
```
BaseRenderer (추상)
└── render(tree: CTTree) → str
├── MarkdownRenderer → Markdown 텍스트
└── JSONRenderer → JSON 문자열
```
**커스텀 렌더러 작성:**
```python
from ctstruct.renderers import BaseRenderer
from ctstruct import CTTree, NodeType
class PlainTextRenderer(BaseRenderer):
def render(self, tree: CTTree) -> str:
lines = []
for node in tree.walk():
if node.content:
lines.append(node.content)
return "\n".join(lines)
```
---
## 4. 데이터 흐름
```
┌──────────────┐ parse() ┌──────────────┐
│ 텍스트 입력 │ ──────────► │ CTTree │
│ (Markdown, │ │ │
│ JSON, etc) │ │ ┌────────┐ │ render() ┌──────────────┐
└──────────────┘ │ │CTNode │ │ ────────────► │ 텍스트 출력 │
│ │ ├child │ │ │ (Markdown, │
│ │ ├child │ │ │ JSON, etc) │
│ │ └child │ │ └──────────────┘
│ └────────┘ │
│ │
│ filter() │
│ map() │ ──► 새 CTTree
│ merge() │
└──────────────┘
```
---
## 5. 노드 속성 규약
각 노드 타입별 `attributes` 딕셔너리의 키 규약:
| NodeType | 속성 키 | 타입 | 설명 |
|----------|---------|------|------|
| `HEADING` | `level` | `int` (1-6) | 헤딩 레벨 |
| `CODE_BLOCK` | `language` | `str` | 코드 언어 |
| `LIST` | `style` | `"ordered"` / `"unordered"` / `"task"` | 목록 스타일 |
| `LIST_ITEM` | `checked` | `bool` | 태스크 목록 체크 여부 |
| `TABLE_CELL` | `align` | `"left"` / `"center"` / `"right"` | 정렬 |
| `TABLE_CELL` | `is_header` | `bool` | 헤더 셀 여부 |
| `LINK` | `href` | `str` | URL |
| `IMAGE` | `src` | `str` | 이미지 경로 |
| `IMAGE` | `alt` | `str` | 대체 텍스트 |
| `METADATA` | (자유형식) | — | frontmatter 키-값 |
---
## 6. 확장 계획
| 단계 | 기능 |
|------|------|
| v0.2 | `PlainTextParser` — 들여쓰기/구분자 기반 텍스트 파싱 |
| v0.2 | `HTMLRenderer` — CTTree → HTML 변환 |
| v0.3 | `JSONParser` — JSON 구조 → CTTree |
| v0.3 | `YAMLParser` — YAML → CTTree |
| v0.4 | `XPathQuery` — 트리 경로 쿼리 언어 |
| v0.5 | 스트리밍 파서 — 대용량 문서 처리 |
| v1.0 | 완전한 CommonMark 호환 Markdown 파서 |
---
## 7. 의존성
```
Python >= 3.10
표준 라이브러리: uuid, re, json, copy, abc, dataclasses, enum
```
개발 도구 (선택):
```
pytest — 테스트
pytest-cov — 커버리지
ruff — 린터
mypy — 타입 검사
```