Files
ParaWiki/Output/reports/ADR-002-feature-dsl.md
minsung 20761ca795
All checks were successful
Publish ParaWiki / build-and-deploy (push) Successful in 31s
Feature DSL 아키텍처 ADR-002 추가
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>
2026-04-14 16:15:34 +09:00

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
특징 형상 기반 모델링 FBM
증분형 갱신 알고리즘 LPG
PCE 파라메트릭 변경 엔진
Revit 조립 단위 분류
선형 GIS 기반 좌표계
ADR-001-tech-stack
비패밀리
증분
선형-GIS

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).
  • 두 도메인 경계에서 명시적 변환 필수. 암묵 변환 금지.
  • 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이므로 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단 계층

BridgeGirder·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부터 기본 탑재:

  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 원칙에 반함. "규칙의 자산화"가 아닌 "인스턴스의 파일화".

후속 결정 필요

  • 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 항목 재검토.