diff --git a/Output/reports/ADR-002-feature-dsl.md b/Output/reports/ADR-002-feature-dsl.md new file mode 100644 index 0000000..6d2a248 --- /dev/null +++ b/Output/reports/ADR-002-feature-dsl.md @@ -0,0 +1,198 @@ +--- +id: ADR-002 +title: cimery Feature DSL — 아키텍처 기본 결정 +status: accepted +date: 2026-04-14 +related-wiki: + - "[[특징 형상 기반 모델링 FBM]]" + - "[[증분형 갱신 알고리즘 LPG]]" + - "[[PCE 파라메트릭 변경 엔진]]" + - "[[Revit 조립 단위 분류]]" + - "[[선형 GIS 기반 좌표계]]" +related-adr: + - "[[ADR-001-tech-stack]]" +principles: [비패밀리, 증분, 선형-GIS] +--- + +# ADR-002 — cimery Feature DSL 아키텍처 + +## 결정 +cimery는 Feature(특징 형상) 생성 규칙을 **Rust 내장(Internal) DSL**로 기술한다. DSL → IR → Evaluator → `GeomKernel`의 4계층 파이프라인, 증분·리액티브 재계산, 타입 수준 단위 강제, Excel 라운드트립 기반의 엔지니어 UX를 기본으로 한다. + +## 배경 +[[특징 형상 기반 모델링 FBM|FBM]]은 "생성 규칙의 자산화"를 요구한다. 이 규칙을 **어떤 언어**로 기술하고, 어떻게 저장·공유·검증·증분 갱신할지가 cimery 아키텍처의 근간이다. + +거더교 MVP의 성격 (이 결정의 전제): +- **내부 파라미터 복잡도**가 본질. 선형·스테이션은 기본 입력일 뿐. +- 계산 비싸고 종속 복잡. +- 재사용 빈도는 **중간** (프리캐스트 거더 ~수십 인스턴스). Revit 패밀리(수천)도, 1회성도 아님. + +## 결정 요약 표 + +| # | 주제 | 결정 | +|---|---|---| +| A | IR(중간표현) | **도입** | +| B | 평가 모델 | **Lazy / Reactive** | +| C | 단위(UoM) | 타입 수준 강제. **구조물 mm, 선형 m** | +| D | 의존성 추적 | **salsa crate** | +| E | IR 직렬화 | **JSON 선행 → MessagePack 승격** | +| F | 단위 구현 | **자체 newtype** (`Mm(f64)`, `M(f64)`) | +| G | Feature 조직 | 초기 **Rust 모듈** → 성숙 후 **WASM plugin** | +| H | salsa 입자도 | **Feature 단위 기본**, 비싼 sub-step만 개별 query | +| I | 기하 커널 호출 | **별도 evaluator 레이어** | +| J | DSL 문법 | **순수 builder** + 얇은 `macro_rules!` 설탕 | +| K | Feature 조합 | **2단 계층** (composite 허용, 공유 그래프 금지) | +| L | 파라미터 검증 | 타입 + `Result<_, FeatureError>` **하이브리드** | +| M | 프로젝트 파일 | 폴더 기반, 플레인 텍스트. **AI·diff 친화 최우선** | +| N | UI 모델 | **템플릿 Export → Excel 편집 → Import → DSL 생성** | +| O | USD 익스포트 | **증분 익스포트 지향** (초기엔 명시 Export) | +| P | 파라미터 선언 | **Rust attribute 매크로** (`#[param(...)]`) | +| Q | Excel 양식 | **CSV만, 단순 Replace** | +| R | 선형 입력 | **자체 포맷 (스테이션 + 점 배열 + 제원)** | +| S | 동시 편집 | **단일 사용자 + Git** | +| T | 테스트 | IR 스냅샷 + 기하 불변량 + 두 커널 cross-check + proptest | + +## 파이프라인 + +``` + [Rust 소스 — Feature DSL (builder + macro_rules!)] + │ + │ #[param(...)] 메타 → CSV 양식 export + │ ← CSV import → DSL 소스 재생성 + ▼ + [IR] ─── JSON/MessagePack 직렬화 · salsa 질의 단위 + │ + ▼ + [Evaluator] + │ + ▼ + [GeomKernel trait] ──► OpenCascade.js (웹) / opencascade-rs (데스크톱) + │ + ├──► 자체 wgpu 뷰어 (주 사용) + └──► USD 씬 익스포트 (Omniverse·IFC 5 파이프라인) +``` + +## 상세 결정 + +### A. IR(중간표현) 도입 +DSL 실행 결과는 기하 호출 이전에 **IR**이라는 데이터 구조로 귀결된다. IR이 있어 직렬화·캐싱·증분·USD 익스포트·스냅샷 리플레이가 전부 깔끔하다. 기하 호출은 IR 이후. + +### B. 평가 모델 — Lazy / Reactive +파라미터 변경 시 **전체 재계산 금지**. 영향권(cone of influence)만 무효화·재계산. [[PCE 파라메트릭 변경 엔진|PCE]]의 직렬 병목을 정면 돌파하는 경로이며 [[증분형 갱신 알고리즘 LPG|LPG 증분]]과 결합한다. + +### C·F. 단위 — 타입 수준 강제, 자체 newtype +- 구조물: `Mm(f64)`. 선형·도로: `M(f64)`. +- 두 도메인 경계에서 **명시적 변환 필수**. 암묵 변환 금지. +- `uom` crate는 토목 도메인엔 과함 — 단위가 한정적이라 자체 newtype으로 명확·가볍게. + +### D. 의존성 추적 — salsa +rust-analyzer가 실사용하는 증분 계산 프레임워크. 질의(query) 기반 자동 메모이제이션·무효화. 바퀴 재발명 회피. 한계 체감 시 자체 DAG 전환 고려. + +### E. IR 직렬화 — JSON → MessagePack +- 초기: JSON — diff·리뷰·AI 가독성 우선. +- 규모 커지면: MessagePack — 이진·컴팩트. bincode는 Rust 종속이라 배제. + +### G. Feature 조직 — 모듈 → WASM plugin +초기엔 `features::girder`, `features::bearing` 같은 Rust 모듈. 라이브러리가 커지고 써드파티 배포가 필요해지면 **WASM plugin**으로 승격. [[ADR-001-tech-stack|Tauri·PWA 듀얼 타깃]]이므로 WASM이 자연스러움. + +### H. salsa query 입자도 +기본은 **Feature 단위 query**. 단, 계산이 비싼 sub-step(단면 생성·스위프 등)은 개별 query로 분해. LPG의 ΔG 노드 = Feature 단위로 매핑 시작. + +### I. 기하 커널 호출 — 별도 evaluator +`GeomKernel` trait 호출은 salsa query 안에서 직접 하지 않고, **evaluator 레이어**에서. IR과 기하 분리로 JSON 직렬화·USD 익스포트·스냅샷 리플레이가 깨끗해진다. + +### J. DSL 문법 — 순수 builder 우선 +```rust +let girder = Girder::builder() + .span(40.m()) + .section(IBeam::new(...)) + .build()?; +``` +proc-macro는 DSL 핵심 문법에는 유보. 반복 패턴이 명확해지면 `macro_rules!`로 얇은 설탕. **단 파라미터 메타데이터 선언(P)에는 proc-macro 허용.** + +### K. Feature 조합 — 2단 계층 +`Bridge`가 `Girder·Bearing·Pier` 등을 포함할 수 있는 composite 허용. 단 **순환·공유 참조 금지** (그래프가 아닌 트리). 초기 복잡도 억제 + 실무 서브 어셈블리 요구 커버. + +### L. 파라미터 검증 — 하이브리드 +- 타입: 음수·단위 불일치 같은 **물리적으로 말 안 되는 것**. +- 런타임 `Result`: 범위·상호제약. +- 에러 메시지에 **경로 포함** — `girder_3.flange_thickness < web_thickness`. + +### M. 프로젝트 파일 구조 — AI·diff 친화 최우선 +**인간 편의는 뒷전.** 폴더 기반, 플레인 텍스트(JSON/TOML), 결정론적 직렬화, 바이너리·zip 배제. IR 캐시는 gitignore. 구성: +``` +project/ +├── project.toml # 메타 +├── features/ # Rust 소스 (Feature 정의·인스턴스) +├── alignment.json # 선형 (자체 포맷) +├── data/*.csv # 엔지니어 입력 +└── .ir-cache/ # gitignore +``` + +### N. 사용자 인터페이스 — Excel 라운드트립 +개발자가 Feature 템플릿(`#[param(...)]` 메타 포함)을 저작. +- 툴 → **CSV 양식 export** (엔지니어에게 친숙한 표). +- 엔지니어 → Excel에서 **값만 입력**. +- 툴 → **CSV import 시 DSL 소스 생성.** +- GUI는 뷰·파라미터 조정만. 주 입력 경로는 CSV 라운드트립. + +### O. USD 익스포트 — 증분 지향 +기본 뷰어는 자체 wgpu. USD는 **Omniverse·IFC 5 파이프라인 연계용**. 초기엔 명시 Export 버튼, 점진적으로 salsa/LPG 무효화 기반 **Prim 단위 증분 익스포트**로 이행. + +### P. 파라미터 선언 — attribute 매크로 +```rust +struct Girder { + #[param(unit = "mm", range = 10..=200, default = 150)] + flange_thickness: Mm, + #[param(unit = "mm", range = 8..=50, default = 12)] + web_thickness: Mm, + // ... +} +``` +AI 친화 — Feature 정의와 메타가 한 파일. Excel export·import 툴이 이 메타를 읽어 양식 생성·검증. + +### Q. Excel 양식 — CSV만, Replace +xlsx·Row ID·보호 영역 **일체 없음**. 재 import 시 기존 인스턴스 전체 교체. 중요 영역이 아니므로 단순화 우선. + +### R. 선형 입력 — 자체 포맷 +```json +{ + "name": "main_alignment", + "stations": [{"station": 0.0, "x": ..., "y": ..., "z": ...}, ...], + "specs": { "type": "highway", "design_speed": 80, ... } +} +``` +LandXML·IFC 4.3 Alignment 변환은 **프로그램 내부 import 루틴**이 담당. MVP 공식 입력은 자체 포맷만. + +### S. 동시 편집 — 단일 사용자 + Git +툴 자체는 파일 락·트랜잭션 없음. 팀 작업은 브랜치·PR·병합 업계 표준 흐름. 실시간 협업(CRDT)은 오버스펙, 장기 비전 유보. + +### T. 테스트·스냅샷 — 견고성 최우선 +네 층 모두 **MVP부터 기본 탑재**: +1. **IR 스냅샷** — `insta` crate, DSL→IR golden 비교. +2. **기하 스냅샷** — 불변량(부피·무게중심·바운딩박스·체크섬) 허용 오차 비교 + 중요 케이스는 STEP diff. +3. **두 커널 cross-check** — 같은 IR이 OpenCascade.js(웹)·opencascade-rs(데스크톱)에서 불변량 일치. +4. **proptest** — 핵심 Feature 2~3개 대상 속성 기반 테스트 (self-intersection 없음·부피 양수 등). + +## USD의 위치 재확인 +USD는 **Feature DSL이 아니다.** USD는 씬 기술 언어이지 규칙 언어가 아니며, 복잡한 파라미터 종속·계산을 표현할 수 없다. Feature DSL이 생성한 결과를 **Omniverse·시뮬레이션·IFC 5 파이프라인에 태우는 출력 포맷**으로 둔다. + +## 기각된 대안 +- **외부 DSL 선행** (OpenSCAD류 전용 문법): 파서·툴체인 자체 구축 비용. Rust 타입 안전성 포기. 필요 시 승격 가능하므로 지금은 아님. +- **비주얼 DSL 선행** (Grasshopper·Dynamo 스타일): diff·AI 가독성 낮음. 뷰어·에디터 구현 부담. 장기 보조 도구로만. +- **Eager 평가**: 거더교 파라미터 수·계산 비용을 감당 못함. PCE의 직렬 병목을 그대로 재현. +- **USD를 DSL 자리에**: 씬 기술 언어로 규칙을 기술하는 것은 구조적 오용. variants·references는 열거형 스위치 수준. +- **Revit Assembly식 바이너리 패밀리 축적**: [[특징 형상 기반 모델링 FBM|FBM]] 원칙에 반함. "규칙의 자산화"가 아닌 "인스턴스의 파일화". + +## 후속 결정 필요 +- [ ] UI 프레임워크 확정 (ADR-001에서 미정 항목 — egui / Yew / Leptos). +- [ ] salsa + GeomKernel 프로토타입으로 증분 성능 측정. +- [ ] 첫 Feature 세트 정의 (거더·받침·신축이음·교각 등 우선순위). +- [ ] WASM plugin 승격 시점·인터페이스 스펙. +- [ ] USD 스키마 매핑 (IfcBridge·IfcAlignment ↔ UsdGeom·UsdPhysics). +- [ ] LandXML/IFC Alignment import 루틴 구현 시점. + +## 검토 시점 +- 첫 거더 Feature 엔드-투-엔드(DSL → IR → 기하 → USD)가 동작할 때 ADR 재검토. +- salsa 증분 성능이 기대 이하면 재검토 — 자체 DAG·Adapton 등. +- IFC 5 + USD 표준화 진전이 있으면 O·R 항목 재검토. diff --git a/wiki/log.md b/wiki/log.md index ff0f13b..cd89f53 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -8,6 +8,7 @@ --- +- 2026-04-14 meta — ADR-002 Feature DSL 아키텍처 작성 (Output/reports/). cimery DSL·IR·salsa·evaluator·Excel 라운드트립 등 20개 기본 결정. - 2026-04-14 meta — Cloudflare Pages 자동 배포 워크플로 추가 (.gitea/workflows/publish.yml). Quartz 4 빌드 → parawiki.pages.dev. - 2026-04-14 create [[선형 GIS 기반 좌표계]] — IfcAlignment·LRS·Geo-BIM 컴파일. 원칙: 선형-GIS. - 2026-04-14 create [[증분형 갱신 알고리즘 LPG]] — Esser LPG 증분 그래프 변환 컴파일. 원칙: 증분.