품질 강화 — ADR-004 + IFC snapshot 테스트 + helper 유닛 + clippy 경고 정리
## ADR-004 (Output/reports/ADR-004-sprint-25-39-decisions.md) Sprint 25~39 기간의 **15개 아키텍처 결정** 정리: - D1~D9: 거더교 MVP 확장 (단면 분기·다경간·Skew 관례·방호벽·격벽·Camber·헌치·UI) - D10~D13: IFC4X3 Add2 익스포터 4 결정 (크레이트 분리·형상 전략 3단계·GUID·Camber 근사) - D14: proc-macro 스캐폴딩 (전면 #[param] 는 Feature 10+ 안정 후) - D15: 변단면 거더 알고리즘 (소핏 lift + Y 선형보간) - 미결 6항목 (Pset 확장·LinearPlacement·ElementAssembly·IfcPile·#[param] 전면·변단면 IFC) - 테스트 커버리지 101개 현황표 ## IFC 스냅샷 테스트 (crates/ifc/tests/snapshot_tests.rs) insta 기반 회귀 방지, 8개 baseline: - mask_guids(): 22자 IFC GUID 를 'GUID' 로 정규화 (결정적 비교 가능) - 시나리오: 기본 단경간 PSC-I / 2경간 π형 / skew 15° / camber 50mm / Rectangle 단면 / parapets off - mask_guids 자체 유닛 테스트 2개 ## Mesh helper 유닛 테스트 (crates/viewer/src/bridge_scene.rs helper_tests) 순수 함수 9개 검증: - apply_camber_mesh: zero 항등·midspan 도달값·경간 밖 미영향 - rotate_y_around_z: 0 회전 항등·90° 피봇 회전·정점 개수 보존 - apply_variable_depth: zero 항등·소핏 lift · 지점 0 lift ## clippy lib 경고 15+ → 0 - map_identity (kernel/expansion_joint.rs) - unnecessary_lazy_evaluations ×4 (dsl/abutment·pier·csv_template — auto-fix) - too_many_arguments (usd save_scene — allow with justification) - clamp-like 패턴 ×7 (viewer bridge_scene/incremental_scene 의 .max(1).min(N) → .clamp(1, N)) - redundant_closure ×2 (project_file 의 `|e| Error::other(e)` → `Error::other`) - redundant_guard ×1 (viewer KeyboardInput match guard → 패턴 내 직접 매치) cargo clippy --workspace --lib: 0 경고. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
239
Output/reports/ADR-004-sprint-25-39-decisions.md
Normal file
239
Output/reports/ADR-004-sprint-25-39-decisions.md
Normal file
@@ -0,0 +1,239 @@
|
||||
---
|
||||
id: ADR-004
|
||||
title: cimery Sprint 25~39 아키텍처 결정 — 거더교 MVP 확장·IFC4X3 Add2·proc-macro 스캐폴딩
|
||||
status: accepted
|
||||
date: 2026-04-15
|
||||
related-wiki:
|
||||
- "[[교각 형식 분류]]"
|
||||
- "[[교각 파라미터 카탈로그]]"
|
||||
- "[[선형 GIS 기반 좌표계]]"
|
||||
- "[[특징 형상 기반 모델링 FBM]]"
|
||||
related-adr:
|
||||
- "[[ADR-001-tech-stack]]"
|
||||
- "[[ADR-002-feature-dsl]]"
|
||||
- "[[ADR-003-architecture-followups]]"
|
||||
principles: [비패밀리, 증분, 선형-GIS]
|
||||
---
|
||||
|
||||
# ADR-004 — Sprint 25~39 아키텍처 결정
|
||||
|
||||
Sprint 1~24 기반 위에서 거더교 MVP 확장과 IFC4X3 Add2 익스포터 Phase 1~3b 구축 중 내린 **15개 결정**을 정리. 이후 세대 에이전트가 설계 의도를 빠르게 소환하도록 한다.
|
||||
|
||||
## 결정 요약표
|
||||
|
||||
| # | 주제 | 결정 | Sprint |
|
||||
|---|---|---|---|
|
||||
| D1 | 단면 타입 분기 | SceneParams `section_type` 로 런타임 분기. `build_selectable_scene` 하드코딩 금지 | 25 |
|
||||
| D2 | `span_m` 의미 | **경간 당** 길이(총 길이 아님). 다경간 총 길이 = span_m × span_count | 26 |
|
||||
| D3 | 피어 MVP 스펙 | wiki 112개 변수 중 **Phase 1 = 30% 입력만**. 기본 사각기둥·CSB 2m | 26 |
|
||||
| D4 | 거더·데크 Skew | **미적용** (precast 거더 관례). 교대·교각·받침·신축이음만 회전 | 27 |
|
||||
| D5 | 방호벽 표현 | 뷰어: 독립 RC 박스 / IFC: `IfcRailing .GUARDRAIL.` | 28 |
|
||||
| D6 | 격벽 표현 | 뷰어 전용 (IFC 미구현, Phase 4 ElementAssembly 로드맵) | 29 |
|
||||
| D7 | Camber 알고리즘 | 포물선 `4·mid·u·(span-u)/span²`, 경간별 독립 적용 | 30 |
|
||||
| D8 | 헌치 Y 기준 | 데크 soffit Y = `bearing_h + girder_h + haunch_depth` | 31 |
|
||||
| D9 | UI 카테고리 | 6 섹션 CollapsingHeader 분리 (상부/바닥판/기하/하부/추가/표시) | 32 |
|
||||
| D10 | IFC 크레이트 분리 | `cimery-ifc` 독립 크레이트. viewer/app 에서 선택적 의존 | 33 |
|
||||
| D11 | IFC 형상 전략 | Phase 1 Rectangle → Phase 2 PSC-I Arbitrary → Phase 3 Alignment | 33-36 |
|
||||
| D12 | IFC GUID | UUIDv4 → base64-22 (buildingSMART charset `0-9A-Za-z_$`) | 33 |
|
||||
| D13 | IFC Camber 근사 | `camber > 0` 시 거더를 N=10 세그먼트 `IfcExtrudedAreaSolid` 로 분할 | 37 |
|
||||
| D14 | proc-macro 스캐폴딩 | `cimery-macros` 최소 선행 — `#[derive(ParamSummary)]` 만, 전면 `#[param]` 은 Phase 2 | 38 |
|
||||
| D15 | 변단면 거더 알고리즘 | 포물선 soffit lift + Y 선형보간 `y_new = y + lift·(1 - y/h)` | 39 |
|
||||
|
||||
---
|
||||
|
||||
## D1. 단면 타입 런타임 분기
|
||||
|
||||
**맥락**: `build_selectable_scene` 가 `SectionType::PscI` 를 하드코딩. 사용자가 SteelBox 를 선택해도 PscI 로 렌더되는 버그.
|
||||
|
||||
**결정**: `SceneParams.section_type` 로 런타임 분기. `build_bridge_scene` 과 동일한 match 패턴 적용.
|
||||
|
||||
**근거**:
|
||||
- 하드코딩은 FBM(비패밀리 원칙) 위반.
|
||||
- `build_bridge_scene` 에 이미 올바른 패턴 존재 → 한 쪽만 틀린 비대칭 버그.
|
||||
|
||||
**영향**: SteelBox·PscU·SteelPlateI 추가 시 `match p.section_type` 에 한 줄만 추가. 카탈로그 확장 비용 최소화.
|
||||
|
||||
---
|
||||
|
||||
## D2. `span_m` 의미 재정의
|
||||
|
||||
**맥락**: 단경간 가정 하에 `span_m = 전체 교량 길이` 로 사용. 다경간 추가 시 의미 충돌.
|
||||
|
||||
**결정**: `span_m` = **경간 당** 길이. `span_count` 신규 도입. `total_mm = span_m × span_count × 1000`.
|
||||
|
||||
**근거**:
|
||||
- 실무 교량 설계는 "경간 × N" 으로 사고 (예: "40m × 3 연속교").
|
||||
- ProjectFile 호환성: v1 저장 파일(`span_count` 없음)은 `default = 1` 로 기존 단경간 동작 유지.
|
||||
|
||||
**대안 기각**:
|
||||
- `total_length_m + span_count` (계산 필요, 사고 무겁)
|
||||
- `span_lengths: Vec<f64>` (MVP 과도, Phase 2+)
|
||||
|
||||
---
|
||||
|
||||
## D3. 피어 MVP 스펙 — wiki Phase 1
|
||||
|
||||
**맥락**: ParaWiki `[[교각 파라미터 카탈로그]]` 의 **112개 변수** vs 현재 `PierIR` ~8개 변수 격차.
|
||||
|
||||
**결정**: Phase 1 MVP = 사용자 입력 **30% ≈ 30개 변수 중 핵심 5개만**:
|
||||
- `pier_type` (T/π), `column_count` (1/2), `column_diameter/depth` (CSB 매트릭스 기본값 2000mm), `column_height`, `cap_beam` 치수.
|
||||
|
||||
나머지 82개 자동계산·상세 변수는 Phase 2~4 로드맵 (wiki 안내 순서).
|
||||
|
||||
**근거**:
|
||||
- MVP 원칙: 기능 축소 OK, 아키텍처 타협 금지.
|
||||
- 112개 전면 구현은 IR·DSL·UI·IFC 4 레이어 동시 확장 필요 → Sprint 1개에 불가.
|
||||
- wiki 의 "Phase 1" 권장 순서가 엔지니어링 검증된 우선순위.
|
||||
|
||||
---
|
||||
|
||||
## D4. 거더·데크 Skew 미적용
|
||||
|
||||
**맥락**: 경사교(skew bridge) 표현 방식 선택.
|
||||
|
||||
**결정**: `skew_deg` 파라미터는 **교대·교각·받침·신축이음에만** Y축 회전 적용. **거더·데크는 직선 유지**.
|
||||
|
||||
**근거**:
|
||||
- Precast 거더 스큐 교량의 **일반 관례** — 거더는 직교 제작, 교대 seat 만 사각으로 절단.
|
||||
- 사각 데크 슬래브는 현장 타설 평행사변형으로 맞춤 (본 MVP 스코프 밖).
|
||||
- 거더 회전 시 mesh 경계 교대와 맞물리는 정합성 문제 발생.
|
||||
|
||||
**영향**: `rotate_y_around_z()` 헬퍼로 지점부 요소만 후처리 회전. 기하 복잡도 최소화.
|
||||
|
||||
---
|
||||
|
||||
## D5~D6. 방호벽·격벽 표현 경로
|
||||
|
||||
**D5 방호벽 (Parapet)**:
|
||||
- 뷰어: 독립 RC 박스(500mm × 1200mm × 전체 길이) 양쪽 엣지
|
||||
- IFC: `IfcRailing .GUARDRAIL.`
|
||||
|
||||
**D6 격벽 (Diaphragm)**:
|
||||
- 뷰어 전용. IFC 미구현.
|
||||
- 향후 `IfcElementAssembly` 로 Pier 그룹 + Diaphragm 포함 예정 (Phase 4).
|
||||
|
||||
**근거**:
|
||||
- IFC 표준에서 방호벽 → `IfcRailing` 이 가장 근접.
|
||||
- 격벽은 IFC4X3 에 전용 엔티티 없음 — `IfcBeam` 또는 `IfcElementAssembly` 내부 원소로 표현.
|
||||
- MVP 에선 격벽을 IFC 스킵하고 뷰어만 지원 → 범위 축소.
|
||||
|
||||
---
|
||||
|
||||
## D7. Camber 알고리즘
|
||||
|
||||
**결정**: 포물선 수식 `y_off(u) = 4 · mid · u · (span - u) / span²`, 경간별 독립 적용.
|
||||
|
||||
**근거**:
|
||||
- 실무 거더 precamber 근사식과 정합 (중앙에서 최대, 양단 0).
|
||||
- 경간별 독립 → 다경간 연속교에서도 각 경간이 올바른 솟음.
|
||||
- 정점 단위 Y 오프셋만 추가 → mesh 생성 파이프라인 변경 최소.
|
||||
|
||||
**구현 위치**: `apply_camber_mesh(mesh, z0, z1, mid_mm)` — 순수 함수, 단위 테스트 가능.
|
||||
|
||||
---
|
||||
|
||||
## D8. 헌치 Y 기준
|
||||
|
||||
**결정**: 데크 soffit Y = `bearing_h + girder_h + haunch_depth` (헌치 0 이면 거더 상면 = 데크 소핏).
|
||||
|
||||
**근거**:
|
||||
- 현실 bridge 단면: 거더 top flange → 헌치 블록 → 데크 soffit 순서.
|
||||
- 단일 변수 `haunch_depth` 로 데크 높이·신축이음·방호벽 기준선 전부 이동 (6군데 일괄 수식 변경).
|
||||
|
||||
---
|
||||
|
||||
## D9. UI 카테고리 6 섹션
|
||||
|
||||
**맥락**: Sprint 14 ~ 31 누적 슬라이더·체크박스 11개가 한 덩어리 섹션에 쌓임.
|
||||
|
||||
**결정**: 6개 `CollapsingHeader` 로 분리:
|
||||
1. 상부구조 (경간·거더 5개)
|
||||
2. 바닥판 (슬래브 두께·헌치)
|
||||
3. 선형·기하 (경사각·솟음·변단면)
|
||||
4. 하부구조 (교각 형식)
|
||||
5. 추가 부재 (가로보·신축이음·격벽)
|
||||
6. 표시 (선형·투영)
|
||||
|
||||
**근거**: Revit UX 패턴과 정합 (카테고리별 속성 분류). 슬라이더 10+ 개 평면 배치는 스캐닝 비용 높음.
|
||||
|
||||
**매크로 hygiene 부산물**: `ps!` 매크로가 외부 `ui` 를 캡처하는 문제를 `ps!($ui, ...)` 명시 매개변수화로 해결.
|
||||
|
||||
---
|
||||
|
||||
## D10~D13. IFC 익스포터 4 결정
|
||||
|
||||
**D10 크레이트 분리**: `cimery-ifc` 독립. viewer/app 에서 선택적 의존 (deps: `cimery-ifc = { workspace = true }`). 크로스 컴파일·WASM 호환성 격리.
|
||||
|
||||
**D11 형상 전략 3단계**:
|
||||
- **Phase 1** (Sprint 33): `IfcRectangleProfileDef` 일률 — 엔티티 계층·워크플로 검증용
|
||||
- **Phase 2** (Sprint 34): `IfcArbitraryClosedProfileDef` + `IfcPolyline` 로 PSC-I 14점 실제 단면
|
||||
- **Phase 3b** (Sprint 36): `IfcAlignment` 독립 엔티티 — LinearPlacement 는 Phase 3c+
|
||||
|
||||
**D12 GUID**: UUIDv4 → buildingSMART base64-22 (`0-9A-Za-z_$` charset).
|
||||
- 대안 기각: IFC1 규격 Base85 — 길이 20자지만 charset 가독성 낮음.
|
||||
|
||||
**D13 Camber 근사**: `camber > 0` 시 거더를 `CAMBER_SEGMENTS = 10` 개 `IfcExtrudedAreaSolid` 로 분할.
|
||||
- 대안 기각 1: `IfcSurfaceCurveSweptAreaSolid` — directrix curve 정의 복잡, 뷰어 지원도 낮음.
|
||||
- 대안 기각 2: 단일 extrude + 속성에 camber 값만 기록 — 기하가 평평함, 시각 검증 불가.
|
||||
- 선택: 다중 세그먼트 포물선 근사. 10 세그먼트 해상도면 ~1mm 오차, BIM 뷰어에서 곡선처럼 보임.
|
||||
|
||||
---
|
||||
|
||||
## D14. proc-macro 스캐폴딩
|
||||
|
||||
**맥락**: ADR-002 D `#[param(unit, range, default)]` 전면 구현 제안 대비 현재 Feature 카탈로그 규모.
|
||||
|
||||
**결정**: Sprint 38 에서 `cimery-macros` 크레이트와 `#[derive(ParamSummary)]` **최소 선행만**. 전면 `#[param]` attribute 는 카탈로그 10+ feature 안정 후.
|
||||
|
||||
**근거**:
|
||||
- 현재 Feature = 거더·데크·받침·피어·교대·가로보·신축이음 7종. 수동 builder 로 관리 가능.
|
||||
- Proc-macro 전면 구현은 큰 투자 — 실제 사용처(중복 보일러플레이트)가 누적돼야 ROI.
|
||||
- 크레이트 인프라(syn/quote) 만 먼저 세팅 → 향후 `#[param]` 추가 시 진입 비용 최소.
|
||||
|
||||
---
|
||||
|
||||
## D15. 변단면 거더 알고리즘
|
||||
|
||||
**결정**: 포물선 soffit lift + Y 선형보간.
|
||||
- `lift(u) = 4 · max · u · (span - u) / span²`
|
||||
- `y_new = y + lift(u) · (1 - y/h)`
|
||||
|
||||
**근거**:
|
||||
- 연속교 중앙부 단면 축소의 물리적 모델: **상면 유지(도로면 평탄) + 소핏 상승** = web 축소.
|
||||
- 선형 보간 계수 `(1 - y/h)` 로 정점 클래스 구분 없이(top/web/bottom 구분 불필요) 균일 처리.
|
||||
- 단일 함수 `apply_variable_depth(mesh, z0, z1, max, girder_h)` — camber 와 독립 조합 가능.
|
||||
|
||||
**영향**: 상수 단면 mesh 생성 후 post-process 만 추가. 커널(psc_i.rs·steel_box.rs) 수정 불필요.
|
||||
|
||||
---
|
||||
|
||||
## 미결·재검토 항목
|
||||
|
||||
- **C1 Pset_BearingCommon / Pset_SlabCommon**: Sprint 35 에서 Pset_BeamCommon 만 구현. 후속 스프린트에서 확장.
|
||||
- **C2 IfcLinearPlacement**: Sprint 36 에서 IfcAlignment 만 추가, 요소 배치는 아직 `IfcLocalPlacement`. Phase 3c.
|
||||
- **C3 IfcElementAssembly**: Pier 의 column + cap beam + footing 을 그룹화. Phase 4.
|
||||
- **C4 IfcPile**: IFC4X3 신규 엔티티. 현재 피어 기초는 IfcFooting 으로 통합 표현. Phase 4.
|
||||
- **C5 `#[param]` 전면 구현**: D14 언급, 카탈로그 확장 시점에 재검토.
|
||||
- **C6 변단면 거더 IFC 반영**: Sprint 37 Camber 와 동일하게 세그먼트 분할 기법 적용 가능.
|
||||
|
||||
---
|
||||
|
||||
## 테스트 커버리지
|
||||
|
||||
Sprint 25~39 기간 추가된 테스트:
|
||||
- `cimery-ifc`: 20 lib + 8 snapshot = 28
|
||||
- `cimery-viewer` mesh helpers: 9 (camber/rotate/variable_depth)
|
||||
- `cimery-macros` derive: 3
|
||||
- 기존 kernel 4층 테스트: 61 유지
|
||||
|
||||
총 **61 + 40 = 101 테스트 통과** 현황.
|
||||
|
||||
---
|
||||
|
||||
## 관련
|
||||
- [[ADR-001-tech-stack]]
|
||||
- [[ADR-002-feature-dsl]]
|
||||
- [[ADR-003-architecture-followups]]
|
||||
- `cimery/crates/ifc/` 구현
|
||||
- `cimery/crates/macros/` 구현
|
||||
- PROGRESS.md Sprint 25~39 타임라인
|
||||
Reference in New Issue
Block a user