cimery Feature DSL의 20개 기본 결정 정리. Rust 내장 DSL + IR + salsa 증분 + 별도 evaluator, CSV 라운드트립 UX, AI·diff 친화 저장 구조. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
id, title, status, date, related-wiki, related-adr, principles
| id | title | status | date | related-wiki | related-adr | principles | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ADR-002 | cimery Feature DSL — 아키텍처 기본 결정 | accepted | 2026-04-14 |
|
|
|
ADR-002 — cimery Feature DSL 아키텍처
결정
cimery는 Feature(특징 형상) 생성 규칙을 Rust 내장(Internal) DSL로 기술한다. DSL → IR → Evaluator → GeomKernel의 4계층 파이프라인, 증분·리액티브 재계산, 타입 수준 단위 강제, Excel 라운드트립 기반의 엔지니어 UX를 기본으로 한다.
배경
특징 형상 기반 모델링 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 파라메트릭 변경 엔진의 직렬 병목을 정면 돌파하는 경로이며 증분형 갱신 알고리즘 LPG과 결합한다.
C·F. 단위 — 타입 수준 강제, 자체 newtype
- 구조물:
Mm(f64). 선형·도로:M(f64). - 두 도메인 경계에서 명시적 변환 필수. 암묵 변환 금지.
uomcrate는 토목 도메인엔 과함 — 단위가 한정적이라 자체 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이므로 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 우선
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<Feature, FeatureError>: 범위·상호제약. - 에러 메시지에 경로 포함 —
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 매크로
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. 선형 입력 — 자체 포맷
{
"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부터 기본 탑재:
- IR 스냅샷 —
instacrate, DSL→IR golden 비교. - 기하 스냅샷 — 불변량(부피·무게중심·바운딩박스·체크섬) 허용 오차 비교 + 중요 케이스는 STEP diff.
- 두 커널 cross-check — 같은 IR이 OpenCascade.js(웹)·opencascade-rs(데스크톱)에서 불변량 일치.
- 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 원칙에 반함. "규칙의 자산화"가 아닌 "인스턴스의 파일화".
후속 결정 필요
- 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 항목 재검토.