diff --git a/docs/raw/조사/2026-10-16_341_부록1_평면종단.md b/docs/raw/조사/2026-10-16_341_부록1_평면종단.md new file mode 100644 index 000000000..5ffd550bf --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록1_평면종단.md @@ -0,0 +1,145 @@ +# 341 가 — 평면 → 종단 (노선 · 측점 · 구조물 · 계획고) · sub1 · 읽기만 + +- 근거 = 코드 읽기(파일:줄) + 340 측정(docs/raw/조사/2026-10-16_340_계산시간_측정.md) · 서버 새로 안 띄움 · 코드 · 계획서 고침 없음. +- 줄임: RE = `B05_Profile/B05_Profile_UI_RouteEdit` · Chain = `B03_FileInput/B03_FileInput_Service_Chain.py` · Replan = `B05_Profile/B05_Profile_Router_Replan.py` · SS = `common_util/common_util_structure_station.ts`(짝 `.py`). + +## 결론 한 줄 + +배수유역을 떼면 노선 점을 놓은 뒤 종단이 다시 보이기까지 0.3 s 는 닿는 거리 — 노선 · 측점 · 계획선 그리기는 TS 짝이 이미 있고, 남는 것은 ① 지반고 표본(지금 서버 65 ms · 아 sub8) ② 「계획고 = 지반고」 첫 계획선(`design_ground_following_profile`) TS 짝 없음 ③ 관 자리 투영(`project_pipe_points`) TS 짝 없음 ④ 노선 바뀐 뒤 사용자 계획고를 어떻게 지킬지 정함(지금은 통째로 버림). + +--- + +## 1. 노선 편집 창 조작마다 — 지금 바로 하는 것 · [확인]까지 미루는 것 + +| 조작 | 브라우저 즉시 계산 | 서버 즉시 요청 | [확인]까지 미룸 | 비고 | +| --- | --- | --- | --- | --- | +| 창 열기 | `flattenServerPlan` RE_Edits.ts:232 · 잠금 읽기 RE.ts:594 · 되돌리기 장부 RE.ts:599 | `GET /route/plan`(Replan:452) · 지형 갈래 · 등고선 · 배수 그림 — 0.54 s | — | 340: 1 s 안 | +| 점 끌기(움직이는 동안) | `buildEditedPolyline` RE_Curve.ts:226(서버 `build_planned_polyline` 짝 · 원호만) · 곡선 하한 검사 RE_Pointer.ts:271-290 | 없음(경사 요청도 끄는 동안 안 함 RE_Slope.ts:179) | 노드 | 3~5 ms | +| 곡선 손잡이 끌기 | `dragHandleTo` RE_Curve.ts:89 · R 하한 RE_Pointer.ts:252 | 없음 | 노드 · R | | +| 점 놓기 | 되돌리기 기록 RE.ts:515 | 단면 띠 `strip.refresh` RE.ts:518(elevations 또는 profile-preview) · 횡단 미리보기 RE_Pointer.ts:320(측점을 보고 있을 때만) · 경사 elevations 250 ms 늦춤 RE_Slope.ts:22,115 | — | 340: 약 0.05 s(elevations 65 ms) | +| 점 더함 · 지움 | `spliceNode` RE_Edits.ts:286 → `applyEdit` RE.ts:429 | 단면 띠 · 경사 | 노드 | 횡단 미리보기는 안 고침 | +| 곡선 R · L · 켬끔 · 잠금(곡선 막대) | RE_CurveBar.ts:63-115 · L→R `deflectionRad` | 단면 띠 · 경사 | curveOn · R | 곡선 잠금 · 호 잠금은 **안 보냄** | +| 꼭짓점 잠금 | RE_CurveBar.ts:102 → `writeRouteLocks` RE_Lock.ts:57 | 계정 설정(pref) 1.5 s 늦춤 | **안 보냄** | [취소]해도 잠금은 남음 | +| 회전 | `createMapRotation` RE_Rotate.ts:48 | 없음(보기 설정만) | — | | +| 경사 표시 | `stationChainages` · `pointsAt` RE_Slope.ts:57/65 | `POST /route/elevations` 250 ms 늦춤 | — | 지반 경사(계획 경사 아님) | +| 되돌리기 · 다시 | RE_History.ts:93/98 → `restoreSnapshot` RE.ts:455 | 단면 띠 · 경사 | — | 메모리 100단 · 페이지 종단 되돌리기와 따로 | +| 재기(측정) | `sampleAlong` RE_Measure.ts:81(2 m) | elevations RE_Measure.ts:203/340 | — | | +| 측점 눈금 눌러 횡단 미리보기 | `stationsAlong` · `curveSpans` · `snapCurveStations` RE_Frame.ts:97/138/160(서버 `Engine_Sections_Core.py` 짝 · 시험 `test_b05_routeedit_frame_mirror.py` · `test_224_2_station_snap.py`) | `POST /route/cross-preview`(Router_Terrain.py:223) | — | 0.7~2 s | +| 측점 맞춤(곡선 중앙) 켬끔 | `setStationSnap` RE.ts:155 | 횡단 미리보기 | station_snap | | +| 노선 추천 알약 · [적용] | `normalizeRouteInitial` RE_Initial_Model.ts:291 | `POST /route/initial`(저장본) | initial(갈래 · 가중) | 마 sub5 자리 | +| 지형 바꿈 | — | 등고선 · 경사 · 띠 · 횡단 다시 받음 RE.ts:643-656 | terrain | | +| [취소] | `cancel` RE.ts:282 | 없음 | 모두 버림 | | +| **[확인]** | `nodes()` RE.ts:559 · 바뀜 판정 RE.ts:561-564 | `POST /route/replan`(Replan:524 · 15분 한도) · 잠금 오버레이 · 끝나면 `clearDrafts` · `clearResults` 뒤 `location.reload()`(RE_Apply.ts:62-68 · design_view_profile.ts:279) | — | 76 s + 다시 열기 2~3 s | + +- 창이 직접 셈하는 것 = 노선 선 · 측점 자리 · 경사 표시용 거리 · 재기. 창이 **안** 셈하는 것 = 지반고(늘 서버) · 계획고(띠는 서버 profile-preview 또는 「계획 = 지반」) · 종단 · 구조물 자리. +- 창의 노선은 메모리에만 — 세션 캐시 없음(새로고침하면 사라짐) · 잠금 · 보기만 계정 설정. + +## 2. 노선 [확인] 체인 — 단계로 쪼갬 + +`POST /route/replan` → `replan_route` Replan:524 → `_recompute` Replan:327 → `run_redesign_chain` Chain:405. 요청 하나가 끝까지 붙잡음. + +| # | 단계 · 하는 일 | 입력 | 출력 | 파일:함수 | 시간 | 초기값 | +| --- | --- | --- | --- | --- | --- | --- | +| 0 | 노선 갈아 끼움 — 노드 → 폴리라인(같은 R 규칙 · 다시 안 뽑음) · 실패 대비 옛 파일 쥠 | 노드 · curve · R · station_snap | `planned_route.csv` + 곡선표 · 노드 파일 | Replan:551-565 `_write_planned_polyline`:239 | 준비 안 | — | +| 1 | 준비 — **관 정본 지움** · 설계 지형 바꿈 · 노선 → BP/EP/CP · stage 2 기록 · 초기값 무효화 | 노선 csv · DB projects · routes | `pipe_points.json` 지움(`clear_pipe_points` Replan:357) · workflow stage 2 | Replan:357-421 · Chain:450-491 | 0.9 s | **지움**(Chain:461 `discard_initial_snapshot`) | +| 2 | 노선 풀기(as_planned · 탐색 없음) + **종횡단 전부 생성**(지반 표본 · 측점 · 계획선) | stage 2 params · 지표면 · structures.json(관은 지워져 0) | DB routes · route_points · 종단 · 횡단 행 · `longitudinal.json` · `cross_*.json` · **새 route_id** | Chain:494-547 → `solve_route` B05_Profile_Router.py:130(생성 :279) → `run_section_generation` Engine_Sections.py:402 | 2.0 s | — | +| 3 | B05 확정 — 상태만 CONFIRMED(`request=None` 이라 비정규 측점 합치기 건너뜀) | DB routes | routes.status | Chain:563 → `confirm_latest_route` Router_Lifecycle.py:35 | 0.1 s | — | +| 4a | 배수유역 큰 계산(refresh) — 다 sub3 몫 | 새 노선 · 등고선 · 도엽 | drainage 단계 파일 | Chain:91 → `get_primary_region` B04_PreProcess_Router_Watershed.py:372 | **60 s** | — | +| 4b | 관 — 파일이 지워져 기본 관 + 최대 간격 보충으로 새로 | 4a 결과 | `pipe_points.json`(노선 지문 · xy) | Chain:103 → `put_pipe_points` B04_PreProcess_Router_Basins.py:432 | 0.3 s | — | +| 4c | 종횡단 **다시 전부 생성**(이번엔 관 측점 포함) · 계획선 처음부터 | pipe_points · structures · stage 2 | DB 종 · 횡단 행 지우고 다시 · json 다시 | Chain:122 → `regenerate_sections` B06_Section_Router.py:378 | 1.5 s | — | +| 4d | (추천 「종단 반영」 켬일 때만) 균형 종단 얹음 | 목표 계획고 | 종단 | `apply_profile_target` B05_Profile_Router_RouteInitial.py:217 | — | — | +| 5 | 설계 이월 — 옛 **횡단 입력**(지반유형 · 측구 · 암선 · 비탈 · 소단 …)을 누가거리 **정확히 같은** 측점에만 얹고 전 측점 재계산 | 옛 cross design 행 · 새 json | DB cross_sections.design | Chain:591-632 → `compute_default_designs` B06_Section_Router_Design.py:615 · 이월 칸 `CARRY_INPUT_KEYS` :199 | 0.9 s | — | +| 6 | B06 확정 + 서버 재계산(면적 · 유토곡선 Node) — 나 sub2 몫 | DB · json · 구조물 | DB design · mass_haul | Chain:637 → `confirm_sections` B06_Section_Router_Confirm.py:293 | 3.1 s | — | +| 7 | 초기 선택 저장 · **초기값 다시 뜸** | 노선 · 종횡단 · drainage 트리 · DB | `initial_snapshot/` | Replan:598-613 → `refresh_initial_snapshot` RouteInitial.py:331 | 안 잼 | **씀** | + +- 배수유역을 빼면 약 9 s(0.9 + 2.0 + 0.1 + 0.3 + 1.5 + 0.9 + 3.1) — 340 의 「6~10 s」와 맞음. +- 2 와 4c 가 같은 종횡단 생성을 두 번 — 2 의 것은 관 없이 만든 뒤 4c 가 통째로 덮음(약 1.5~2 s 헛일). +- 3D 길 모형(코리도)은 이 체인에서 안 지음(`prebuild_corridor` 는 자동설계 체인만 Chain:328) — 초기값에 옛 코리도가 들어갈 수 있음(나 sub2 · 라 sub4 참고). + +## 3. 단계마다 실시간 길 + +조작 중 = 브라우저가 같은 코드로 즉시(①짝 · ②TS→서버 Node) · [저장]·[확정] = 서버 정본으로 다시. 0.3 s 목표 = 「점 놓기 → 종단 그림」. + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 노선 선(노드 → 폴리라인) | ts `buildEditedPolyline` RE_Curve.ts:226 ↔ py `build_planned_polyline`(common_util_route_polyline.py) · ① 짝 이미 · 3~5 ms | 그대로 씀 · 거울 시험을 `resources/tester` 로 옮김(지금 `tmp/tests/test_route_polyline_browser_mirror.py` — git 밖) | 시험 1 | 이미 즉시 | 거울 시험이 tmp 에 있어 지켜지지 않음 | S | +| 일반 측점(20 m 격자 · 끝 · 곡선 중앙 맞춤) | ts `stationsAlong` · `curveSpans` · `snapCurveStations` RE_Frame.ts:97/138/160 ↔ py `Engine_Sections_Core.py` · ① 짝 이미(`test_b05_routeedit_frame_mirror.py`) · ms | 노선 바뀔 때마다 이것으로 측점표를 새로 세움 | 0~1 | 즉시 | 서버 `_chainages` 와 끝 측점 · 맞춤 규칙 다시 대조 | S | +| 구조물 측점(structures.json) | 누가거리로 저장 · 노선 바뀌어도 **안 옮김**(Replan.py:21-24 「옛 측점값 그대로」) · 측점 = `planStations` SS.ts:185 ↔ `plan_stations` · ① 짝 | 그대로(누가거리 고정)면 할 일 없음 · xy 로 따라가게 하려면 structures 에 좌표 저장 + 투영 짝 새로 | 0 또는 4~6 | 즉시 | 노선을 앞쪽에서 고치면 구조물이 땅 위 다른 자리로 밀림 — 사용자 뜻 확인(물을 거리 3) | S / M | +| 관 자리(pipe_points.json) | [확인]이 **지우고 배수유역으로 새로**(Replan:357 → Chain:103) · 투영 이월 py `project_pipe_points` common_util_drainage_pipes.py:211(xy 투영 + 정수 m 맞춤 `snap_structure_station`) 이 있으나 replan 은 안 씀 · ts 짝 없음 | 조작 중 = 저장 xy 를 새 노선에 투영(ts 짝 새로 · `snapStructureStation` SS.ts:52 는 이미 짝) · [저장] = 서버 같은 투영 · 배수유역 갱신은 다 sub3 길(뒤에서 · 수동) | 3~4(ts 1 · 거울 시험 1 · 체인 1 · 화면 1) | 즉시(ms) | 지우지 않으면 사용자 관 편집이 남음(지금은 사라짐) — 대신 노선이 크게 바뀌면 계곡을 벗어난 관이 남음 → 배수유역 갱신 때 덮을지 다 sub3 와 맞춤 | M | +| 비정규 측점 합치기 · 계획고 노드 따라가기 | ts `plantedChainages` :236 · `oneStationList` :259 · `followMovedNodes` :281 ↔ py `resolve_extra_stations` Engine_Sections.py:260 · `_merge_irregular_into_longitudinal` Router_Confirm.py:295 · `_follow_moved_stations` :204 · ① 짝 이미(`test_272_1_station_list.py`) · ms | 그대로 씀 — 일반 측점 + 구조물 · 관 측점을 한 벌로 | 0 | 즉시 | `followMovedNodes` 는 0.006 m · 반올림 정수만 따라감 — 노선 바뀜처럼 수 m 밀림엔 노드를 지움(아래 5장) | S | +| 종단 지반선(표본) | 서버만 — 화면은 저장된 `profile_alignment.samples[].ground_elevation_m` 을 읽음(B05_Profile_UI_Profile_Alignment.ts:171-183) · 편집 창 띠는 `POST /route/elevations` Router_Terrain.py:79 · py · 65 ms | **아 sub8 몫** — 쓸 자리: 측점 + 종단 표본 간격 점 xy 묶음 → z · 서버 왕복이면 1회 65 ms(0.3 s 안 들어옴) · 브라우저 표본이면 ms | — | 65 ms → ms | 지형 갈래(las/sheet) · 무효 자리 `valid=false` 를 브라우저도 같게 | (sub8) | +| 첫 계획선(계획고 = 지반고 · 전 측점 변화점) | py `design_ground_following_profile` Engine_Grade_Profile.py:168(호 대칭 · 꼭짓점 반복 보정) · 체인 2 · 4c 에서 · **ts 짝 없음** | ① 짝 새로 — 측점별 지반고 → base_pvi · 거울 시험 · 그 위는 이미 ts `buildAlignment` Alignment.ts:394 ↔ `Engine_Grade_Alignment.py` | 3(ts 1 · 시험 1 · 머리 주석 py 1) | ms | 2순위 이하 폴백(관 정착 · 직선 분할 · 균형)까지 짝을 만들지 — 1순위만 짝, 실패 때만 서버로 추천 | M | +| 사용자 계획고(편집) 지키기 | 노선 바뀌면 **버림** — 체인이 `edits=None` 으로 새로 풂(Engine_Sections.py:288-341) · 화면 쪽 이월 코드(design_profile.ts:513-526)는 reload · `clearDrafts` 로 안 닿음 | 5장 안 중 하나 | 2~3 | 즉시 | 사용자 뜻(물을 거리 1) | M | +| 계획선 → 종단 그림 | ts `buildAlignment` 0.9 ms · 종단 다시 그림 약 48 ms(340 측점 고르기) | 그대로 | 0 | 50 ms | — | S | +| 전 측점 횡단 · 유토곡선 | ts `refreshCrossDesigns` 88 ms(340) · 횡단 지반 표본은 서버 | **나 sub2 · 아 sub8 몫** — 종단 그림보다 뒤(다음 틀)로 미뤄 0.3 s 계산에 안 넣음 | — | — | 노선 바뀌면 횡단 지반 표본도 다 새로 | (sub2·8) | +| 노선 · 측점 · 계획선 [저장] | 지금 [확인] = 체인 9 s(배수유역 뺌) + 종횡단 두 번 생성 | 서버 정본 재계산 = 0 → 2 → 4b(투영) → 4c → 5 → 6 · 2 의 종횡단 생성 빼고 한 번만 · 배수유역은 떼어 냄 | 2~3(Replan · Chain) | 9 s → 약 6~7 s · 오버레이 자리 | 새 route_id 를 [저장] 때 한 번만(조작 중 DB 행 안 만듦) | M | +| 3D 길 모형 | 이 체인에서 안 지음 · 화면 1.9 s 긴 작업 | 마 sub5 · 나 sub2 몫 | — | — | — | — | + +## 4. 측점 한 벌 짝 · 노선이 바뀌는 동안 구조물이 따라가는 길 + +- 짝 목록(SS.ts 머리 19-23 · py Router_Confirm.py:234 · 307 에 짝 적힘): + +| ts | py | 시험 | +| --- | --- | --- | +| `planStations` SS.ts:185 | `plan_stations` | test_322_3_plan_mirror.py | +| `plantedChainages` :236 | `resolve_extra_stations` Engine_Sections.py:260 | test_272_1_station_list.py | +| `oneStationList` :259 | `_merge_irregular_into_longitudinal` Router_Confirm.py:295 | test_272_1_station_list.py | +| `followMovedNodes` :281 | `_follow_moved_stations` Router_Confirm.py:204 | (없음 — 272_1 helper 가 부르기만) | +| `snapStructureStation` :52 | `snap_structure_station` | test_234_1_structure_station.py | +| (없음) | `project_pipe_points` common_util_drainage_pipes.py:211 | — | +| `stationsAlong` 등 RE_Frame.ts:97 | Engine_Sections_Core.py | test_b05_routeedit_frame_mirror.py | + +- 짝은 모두 **누가거리를 받아** 측점을 만듦 — 노선 기하에서 누가거리를 다시 매기는 짝(관 xy 투영)만 빠짐. +- [확인] 체인에서 `_merge_irregular…` · `_follow_moved…` 는 안 돎(B05 확정 `request=None` · Lifecycle) — 4c 가 측점을 통째로 새로 만들기 때문. +- 지금 따라가는 방식: 구조물 = 누가거리 고정(xy 는 새 노선 위 그 누가거리 자리로 옮겨짐) · 관 = 지우고 배수유역이 새로 · 노선 [확인] 전 미리보기에는 둘 다 안 보임. +- 실시간 안: 노선 바뀔 때마다 ① 일반 측점 `stationsAlong` ② 관 = 저장 xy 투영(ts 짝 새로) ③ 구조물 = 누가거리 그대로 ④ `plantedChainages` → `oneStationList` 로 한 벌 — 모두 ms. + +## 5. 노선이 바뀐 뒤 계획고 + +- 지금: [확인] 체인이 계획선을 처음부터 다시 풂 — 1순위 `design_ground_following_profile`(전 측점 계획고 = 지반고 · Engine_Sections.py:308) · `edits=None` · 옛 `profile_alignment`(base_pvi · station_offsets · curve_radii)는 안 읽음. 사용자가 고친 계획고 · 종단곡선 R 은 **모두 사라짐**. 예외 = 추천 「종단 반영」 켬(`apply_profile_target`). +- 편집 키 = 누가거리 글자(`toFixed(3)`) — 노선이 바뀌면 같은 키가 다른 땅을 가리킴 · 그대로 얹으면 엉뚱한 자리에 높낮이가 붙음. +- 실시간 안 셋(크기 M): + - 가) **지반 다시 맞춤(지금 규칙 그대로)** — 노선이 바뀌면 계획고 = 새 지반고 · 사용자 편집 버림 · 계획선 짝 하나로 끝 · 단순 · 지금 [확인]과 같은 결과. + - 나) **바뀐 구간만 다시 맞춤** — 노선 변경 앞뒤 누가거리 범위(바뀐 노드의 앞 · 뒤 접선점)를 찾아 그 밖 편집은 거리 차만큼 밀어 지키고 안은 지반 맞춤 · 편집 창 노드 번호로 범위 앎 · 짝 하나 더(편집 옮기기). + - 다) **편집 비율 옮김** — 누가거리 비율로 전 편집을 늘이고 줄임 · 짧지만 땅과 안 맞음 · 비추천. +- 추천 = 나) — 노선 끝쪽을 고쳤는데 앞쪽 계획고가 날아가는 것을 막음 · 범위 밖 편집은 거리만 밀림이라 같은 땅. + +## 6. 0.3 s 목표 — 노선 점 놓기 → 종단 다시 보임 + +| 칸 | 지금 | 실시간 뒤(추정) | 남은 일 | +| --- | --- | --- | --- | +| 노선 선 · 일반 측점 | ms(짝 있음) | ms | 없음 | +| 구조물 · 관 측점 | 미리보기 없음 | ms | 관 투영 ts 짝(M) | +| 지반고(측점 + 종단 표본) | 서버 65 ms(elevations · 점 묶음 한 번) | 65 ms 또는 ms | 아 sub8 — 한 요청으로 묶음 · 지형 갈래 같게 | +| 첫 계획선 · 편집 옮김 | 서버 체인 안 | ms | ts 짝 · 5장 나) | +| `buildAlignment` | 0.9 ms | 0.9 ms | 없음 | +| 종단 다시 그림 | 약 48 ms | 약 48 ms | 없음 | +| 합계 | 76 s + 다시 열기 2~3 s | **약 0.12 s(서버 표본) · 0.05 s(브라우저 표본)** | 위 셋 | + +- 횡단 · 유토곡선은 종단 그림 뒤 다음 틀(나 sub2) — 0.3 s 계산 밖. +- 끄는 동안(점 움직임)은 지금처럼 선만 · 놓을 때 한 번 위 계산 — 지반 요청이 끄는 중에 쌓이지 않게(`designRequestSeq` 처럼 최신만). + +## 7. 규칙 바꿀 거리(CLAUDE.md 5장과 부딪힘) + +1. 초기값 쓰기 자리 — 지금 「노선 [확인] 직후」 초기값을 다시 뜸(Replan:614). 노선 편집이 본문으로 오고 [확인]이 없어지면 쓸 자리가 사라짐 → 「노선이 바뀐 [저장] 직후」로 바꿀지, 초기값을 자동설계 체인 한 번만으로 둘지. +2. 노선 [확인]의 잠금 오버레이 · 「노선 재탐색」 자리 — 실시간이면 노선 조작은 오버레이 없음 · 오버레이는 [저장] 한 곳으로. +3. 노선 변경이 새 route_id 를 만드는 것(solve 마다 DB 행) — 실시간에서는 [저장] 때 한 번만 · 그 사이 노선은 캐시(sessionStorage)층 — 노선 편집 창은 지금 캐시 없이 메모리만이라 「조작은 캐시에」 규칙 밖. + +## 8. 관찰(고치지 않음) + +- 2 와 4c 종횡단 두 번 생성(약 1.5~2 s 헛일). +- 노선 거울 시험 `test_route_polyline_browser_mirror.py` 가 `tmp/tests`(git 밖)에 있음. +- 꼭짓점 · 곡선 잠금은 서버로 안 감 · [취소]해도 잠금은 남음. +- 곡선 막대 · 점 더함 · 지움 · 되돌리기 뒤 열린 횡단 미리보기가 안 고쳐짐(점 놓기만 고침). +- `B05_Profile_Api_Replan.ts:12` 주석은 「[확인]이 지형을 안 보냄」이라 하나 RE_Apply.ts:101 은 보냄. +- [확인]이 관 정본을 지워 사용자 관 편집(종류 · 관경 · 자리)이 매번 사라짐(Replan.py:21-24 의 정해진 동작). + +--- + +## 사용자에게 물을 거리 + +1. 노선을 고치면 사용자가 고친 계획고를 어떻게 — 가) 전부 새 지반에 다시 맞춤(지금) · 나) 바뀐 구간만 다시 맞추고 나머지 지킴 · 다) 비율로 옮김 → **추천 나)**. +2. 노선을 고치는 동안 관(횡단배수) 자리 — 가) 저장 자리(좌표)를 새 노선에 붙여 따라감 · 나) 지금처럼 지우고 배수유역이 새로 → **추천 가)**(배수유역은 떼어 수동 · 다 sub3 와 맞춤). +3. 노선을 고치는 동안 구조물(옹벽 · 세월교 등) 자리 — 가) 측점(누가거리) 그대로(지금 · 땅 위 자리는 밀림) · 나) 땅 위 자리 그대로(누가거리 다시) → **추천 가)** 지금 유지 · 앞쪽 노선 고침 때 밀림 표시만. +4. 노선 편집이 본문으로 오면 초기값([초기화]가 돌아갈 자리)을 언제 — 가) 자동설계 체인 한 번만(노선 고쳐도 안 바뀜) · 나) 노선 바꾼 [저장] 때마다 다시 → **추천 가)**(초기값 = 처음 자동설계 · 「규칙 바꿀 거리」 1). +5. 노선 점을 놓은 뒤 종단만 0.3 s · 횡단 · 유토곡선은 그다음(1 s 안) 순서로 괜찮은지 → **추천 예**. diff --git a/docs/raw/조사/2026-10-16_341_부록2_종단횡단.md b/docs/raw/조사/2026-10-16_341_부록2_종단횡단.md new file mode 100644 index 000000000..d43795365 --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록2_종단횡단.md @@ -0,0 +1,99 @@ +# 341 나 — 종단 → 횡단 → 유토곡선 (3D 길 모형 포함) · 실시간 연동 검토 (sub2 · 읽기만) + +- 근거 시간 = docs/raw/조사/2026-10-16_340_계산시간_측정.md(66 측점 · 검증_sub2 노선 232). +- 확인 방법 = 코드 읽기 + 저장본(GET detail · pipe-points 8004 · 검증_sub2)으로 브라우저 함수 그대로 Node 에서 재현(scratchpad · 코드 · 값 안 바꿈). +- 결론 한 줄 = 횡단 · 유토곡선 계산은 이미 브라우저 TS 로 0.1 s 안 — 노선 변경에도 같은 창구를 쓰면 됨 · 막는 것은 측점 · 지반 표본 입력(가 · 아 몫)과 「계획선 두 벌」 흠 · [전체 측점 반영] 4.1 s 는 같은 계산을 66 번 되풀이한 것. + +## 1. 지금 길 — 계획고 · 노선이 바뀌면 무엇이 다시 되나 + +| 단계 | 지금 자리(파일:줄 · 함수) | 언어 | 시간 | +| --- | --- | --- | --- | +| 계획고 ▲▼ → 편집 델타 | design_profile.ts:388(Render 안 onStation) → `adjustStation`(B05_Profile_UI_Profile_Alignment.ts:556) | TS | 4 ms | +| 횡단 다시 셈 예약 | `createCrossPreview.schedule`(B05_Profile_UI_Profile_Preview.ts:46) · 디바운스 16 ms(종단 보기) · 120 ms(횡단 보기)(design_profile.ts:122 · 396) | TS | — | +| 전 측점 횡단 설계 | `refreshCrossDesigns` → `refreshLocally`(B06_Section_Cross_Refresh.ts:182 · 290) → `computeCrossDesign`(common_util_cross_design.ts) · 파이썬 짝 `B06_Section_Engine_Design.py` | TS(① 짝) | 66 측점 88 ms(p50) | +| 구조물 폐회로 면적 | `applyStructureAreaRows`(Cross_Refresh.ts:189) | TS(② 서버 Node 짝) | 15 ms | +| 카드 · 종단 다시 그림 | `refreshCards`(B06_Section_UI_Section_View.ts:516) · `onApplied → draw`(design_profile.ts:397) | TS | 바뀐 카드만 · 종단 ≈ 50 ms | +| 유토곡선 | `computeMassHaulSeries`(B05_Profile_UI_Profile_MassHaul.ts:390) | TS | 0.4 ms | +| 흙 배분 | `haulPrefetch.schedule`(MassHaul.ts:339) → POST haul-plan(B05_Profile_Api_HaulPlan.ts · 대기 400 ms :21) → `compute_haul_plan`(B06_Section_Router_HaulPlan.py:43) → Node | 서버 Node | 0.13 s(처음 0.75 s) | +| 3D 길 모형 | [3D 업데이트](B05_Profile_UI_Panel_View.ts:77) → `refreshCorridor`(B05_Profile_UI_Corridor.ts:251) → `refreshStaleDesigns`(:262) → `corridorHash`(:171) → `buildCorridor`(:196 · _Corridor_Build.ts:140) → `setCorridor` · 처음엔 PUT 15 MB(:209 · :229) | TS 주 스레드 한 덩이 | 1.6~2.0 s(화면 멈춤) · 처음 PUT 2.2 s | +| 3D 낡음 표시 | 횡단이 바뀌면 `setCorridorPending(true)`(design_view_profile.ts:155) — 자동으로 안 지음 | TS | — | +| [전체 측점 반영] | `applyPanelToAll`(B06_Section_UI_Page_Design_Sync.ts:222) → 측점마다 `handleDesignChange`(:64) → `reconcileStaleDesigns(force)`(:158) → **전 측점** `refreshCrossDesigns` | TS | 66 × 약 62 ms = 4.1 s | +| 횡단 [확정] | `crossSaveParts`(B06_Section_UI_Page_Persist.ts:491) → `confirmSections`(B06_Section_Api_Fetch.ts:173) → `confirm_sections`(B06_Section_Router_Confirm.py:293) → `recompute_server_side`(B06_Section_Server_Calc_Prebuild.py:204) → Node 면적 · 유토곡선 | py + 서버 Node | 2.2 s(Node 0.2 · 정본 저장 0.7) | +| 노선 [확인] 뒤 횡단 | `run_redesign_chain`(B03_FileInput_Service_Chain.py:405) → `regenerate_sections`(B06_Section_Router.py:378) → `generate_sections`(B05_Profile_Engine_Sections_Core.py:346) · 이월(:587-630) → 확정 · 화면은 `clearDrafts` · `clearResults`(B05_Profile_UI_RouteEdit_Apply.ts:64-65) | py(③ 서버 단독) | 배수유역 빼고 6~10 s | + +## 2. 계획고 즉시 길을 노선 변경에도 쓰나 + +- 쓸 수 있음. `refreshLocally` 는 측점마다 `samples`(지반선) · 계획고 · 측점 기하(`plan_radius_m` · `curve_outer_side` · `curve_widening_m`) · 세션 선택만 받아 TS 로 셈 — 노선 변경 = 이 입력을 새 측점 목록으로 갈아 끼우는 일. +- 입력 중 지금 서버만 만드는 것: + - 측점 목록 · 중심 · 방향 · 곡선 확폭 — `generate_sections`(Engine_Sections_Core.py:346) → 가 sub1 몫. + - 측점 지반선 표본 — `sampler.sample_xy`(Engine_Sections_Core.py:438 · 515-532) → 아 sub8 몫(브라우저 지형은 3D `heightAt`(B05_Profile_UI_Corridor_Terrain.ts:108) 하나뿐). +- 측점이 늘거나 빠질 때 지금 사정: + - 세션 초안 키 = 누가거리 `toFixed(2)`(B06_Section_Cross_Design_Session.ts:31) · 측점이 움직이면 옛 키가 안 맞아 **조용히 버려짐**(옮김 없음). + - 서버 이월 = `round(chainage,3)` **정확히 같은 자리만**(Service_Chain.py:593) · `CARRY_INPUT_KEYS` 일곱(B06_Section_Router_Design.py:199 — 지반 유형 · 측구 종류 · 측구 선택 · 2단 경사 · 암 경계 · 암 경사 · 소단). + - 이월 안 됨 = `USER_TOUCHED_KEYS`(Router_Design.py:151 · Cross_Refresh.ts:82) 중 구조물 조정(basin · revet · ford · box) · extra_spans · 글 · 표 · 노견 확장 · 소단 깊이. + - 자릿수 셋이 섞임 — 세션 0.01 m · 서버 이월 0.001 m · 관 지점 0.01 m · 서버 측점 0.001 m(아래 4장 흠의 뿌리). +- 지킬 길(안): 측점 정체성을 둘로 — + - 일반 측점 = 누가거리 격자 번호(No.k · 노선 모양이 바뀌어도 같은 수 · 길이가 줄면 끝 쪽만 사라짐). + - 구조물 측점 = 구조물 · 관 id(관이 옮겨도 고침이 따라감 · 지금 `followedStation`(B05_Profile_UI_Page_Structures.ts:88) 이 계획고 편집에만 하는 일을 횡단 고침에도). + - 자릿수 한 규칙(0.01 m)을 TS · 파이썬 양쪽. + - 사라진 측점의 고침은 「노선 밖으로 나간 고침 N 건」 한 줄로 알림. + +## 3. 표 — 실시간 안으로 넣는 길 + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 계획선 한 벌 | 화면 = `listed()` 로 만든 선(design_profile.ts:348-370 · 관 측점 · 옮긴 꼭짓점 반영) · 다시 셈 = 저장본 선(Cross_Refresh.ts:292-300) — 두 벌 · TS | 다시 셈이 화면이 쥔 선(`alignment`)을 받아 씀 — `CrossRefreshInput` 에 선 하나 더함 | 3(Cross_Refresh · Profile_Preview · design_profile) | 유토곡선 머묾 사라짐 · 노선 변경 때도 같은 선 하나 | B06 `reconcileStaleDesigns`(Design_Sync.ts:158) · 3D `refreshStaleDesigns`(Cross_Refresh.ts:160)도 같은 선을 받게 · 거울 시험 | S | +| 낡음 「한 번만 묻기」 | `scheduleIfStale`(Profile_Preview.ts:42) · `staleKey`(B06_Section_UI_Section_Common.ts:110) — 다시 셈 뒤에도 낡으면 같은 지문이라 다시 안 묻고 곡선은 「다시 계산하는 중」에 멈춤 · haul-plan 도 안 나감(MassHaul.ts:348 · 381) | 다시 셈 뒤에도 낡으면 곡선은 그리고 낡은 측점만 표시 · 콘솔 경고 | 2(MassHaul · Profile_Preview) | 조용한 멈춤 → 보이는 경고 | 「새 값만 보여주기」(2026-09-03 사용자 확정)와 부딪힘 — 물을 거리 6 | S | +| [전체 측점 반영] | `applyPanelToAll`(Design_Sync.ts:222-239) — 측점마다 전 측점 다시 셈(66 × 66) · TS · 4.1 s | 측점 선택 기록 없이 다시 셈 한 번(`reconcileStaleDesigns({force:true})`) — 표준값은 `effectiveStandardCross`(Cross_Refresh.ts:294)가 이미 읽음 | 1(Design_Sync) | 4.1 s → 약 0.1 s + 바뀐 카드 그리기(최대 0.5 s · 보이는 것 먼저면 0.1 s) | 지금은 측점마다 현재 값을 「사용자 선택」으로 박음(:108-116 · `changeFromDesign` :122) — 자동 판정(단면 유형 · 측구 방향)이 선택으로 굳어 노선이 바뀌어도 재판정 안 됨 · 박는 동작이 일부러인지 확인 | S | +| 노선 변경 → 전 측점 횡단 | 서버 체인만(Service_Chain.py:405 · 6~10 s + 배수유역 60 s) | 새 측점 · 표본이 오면 `refreshCrossDesigns` 그대로(① 짝 유지) · 서버는 [저장] 때 같은 엔진으로 정본 | 2~3(Cross_Refresh 입력 · 측점 공급 자리) + 가 · 아 몫 | 횡단 설계 88 ms + 면적 15 ms ≈ 0.1 s(표본 시간 별도) | 측점 기하(곡선 확폭 · 방향)가 TS 로 나와야 — 가 sub1 · 표본 — 아 sub8 | M | +| 측점 늘고 빠질 때 고침 지키기 | 세션 키 0.01 m · 서버 이월 0.001 m 정확히 · 이월 키 일곱 · 옮김 없음(2장) | 일반 = 격자 번호 · 구조물 = id 키 · 자릿수 0.01 m 하나 · 노선 밖 고침 알림 | 5~7(Cross_Design_Session · Section_Drafts · Page_Persist · Router_Design.py · Service_Chain.py · Page_Structures) | 노선을 바꿔도 측구 종류 등 남음 | 같은 격자 자리라도 지형이 바뀌면 옛 단면 유형 · 측구 방향이 안 맞음 — 어느 키를 넘길지 물을 거리 1 | M | +| 횡단 카드 그리기 | 종단 → 횡단 보기 0.54 s(카드 SVG 66) · `refreshCards`(Section_View.ts:516) 바뀐 카드 전부 | 보이는 카드 먼저(IntersectionObserver) · 나머지는 쉬는 틈에 나눠 | 2(Section_View · Cross_View) | 노선 변경 때 0.5 s → 약 0.1 s | 화면 밖 카드의 경고칩 · 면적 합(유토 뱃지)은 계산값이라 영향 없음 · 그리기만 늦춤 | M | +| 유토곡선 · 흙 배분 | 0.4 ms TS · 배분 0.13 s 서버 Node(대기 400 ms) | 그대로 — 위 두 흠만 고치면 노선 변경에도 따라옴 | 0 | 0.4 ms + 뒤에서 0.13 s | 배분 응답 늦게 온 옛 값 — 입력 키 비교(HaulPlan.ts)가 있는지 고칠 때 확인 | S | +| 3D 길 모형 짓기 | `buildCorridor`(Corridor_Build.ts:140) 주 스레드 1.6~2.0 s · TS | 웹 워커(이미 서버 Node 에서 도는 순수 계산 — B05_Profile_Corridor_Node.ts:42 · 지금 저장소에 워커 없음) · 조작 멈춘 뒤 1 s · 3D 창이 열렸을 때만 · 「3D 늦음」 표시는 `setCorridorPending` 재사용 | 3~4(워커 진입 새 1 · Corridor.ts · vite 설정 · Viewer_Corridor) | 화면 멈춤 1.9 s → 0 · 3D 는 약 2 s 늦게 따라옴 | 결과 15 MB 넘김 0.1~0.3 s(Transferable 로 줄임) · `setCorridor` 심 보정(지형 heightAt)은 주 스레드에 남음(첫 틀 52 ms) · 3D 가 모달로 가면(마 sub5) 닫힌 동안 안 지음 | M | +| 3D 저장 올림 | 브라우저가 지은 15 MB 를 PUT(Corridor.ts:209 · 229 → B05_Profile_Router_Corridor.py:131) · 처음 2.2 s | [저장] 때 서버 Node `prebuild_corridor`(B05_Profile_Corridor_Prebuild.py:47)가 다시 지음 · 노선 [확인] 체인에도(지금 `run_redesign_chain` 은 안 부름) | 3(Corridor.ts · Persist 저장 줄 · Service_Chain.py) | 올림 2.2 s 사라짐 · [저장] 잠금 안 +1~1.9 s | 5장 「브라우저 값을 받아 적지 않음」과 지금이 어긋남 — 규칙 바꿀 거리 R1 · 라 sub4 와 겹침 | M | +| 횡단 [확정] | 2.2 s(py + Node · 정본 저장 0.7 s) | 그대로(잠금 오버레이 자리) · 정본 저장 0.7 s 는 라 sub4 | 0 | — | — | S | + +## 4. 유토곡선 「다시 계산하는 중」 머묾 — 까닭(고치지 않음) + +- **재현됨** — 검증_sub2 저장본만으로(세션 없이) Node 에서 화면과 같은 함수를 돌림. +- 까닭 = **계획선 두 벌**. + - 화면은 `listed()`(design_profile.ts:348)로 선을 만듦: 측점 목록을 관 지점(0.01 m · 85.05)으로 갈음 · 서버 측점(0.001 m · 85.052)은 「사라짐」 · 거기 있던 꼭짓점 9 개를 `followMovedNodes`(common_util_structure_station.ts:281)로 2 mm 옮김. + - 다시 셈은 저장본 선(Cross_Refresh.ts:292-300 · 서버 측점 · 안 옮긴 꼭짓점)으로 계획고를 설계에 적음. + - 그리기의 낡음 판정(B05_Profile_UI_Profile_Render.ts:229 · 427)은 화면 선과 견줌 → 측점 258.123 · 533.975 에서 1.4 · 2.0 mm 어긋남 > 허용 1 mm(Section_Common.ts:100) → 늘 낡음. + - 다시 셈 뒤에도 지문이 같아 `scheduleIfStale` 이 다시 안 부름(Profile_Preview.ts:43) · 계획고를 눌러 다시 셈해도 같은 저장본 선이라 그대로 → 「다시 계산하는 중」 고정. + - 그 사이 `emitSummary` 를 건너뛰어(MassHaul.ts:348 · 381) haul-plan 이 안 나감 — 340 관찰과 같음. +- 어느 프로젝트에나 생길 수 있음 — 관 지점 0.01 m 와 서버 측점 0.001 m 가 다르고 그 자리가 종단곡선 안이면. +- 340 의 「함수를 직접 부르면 낡음 0」은 저장본 선끼리 견준 값(화면 선이 아님)이라 안 걸린 것. +- 실시간 연동의 위험: 같은 값을 두 곳에서 만들면 판정이 갈려 화면이 조용히 멈춤 — 노선까지 실시간이 되면 선 · 측점 목록을 만드는 곳이 더 늘어남 → **「계획선 · 측점 목록은 한 곳에서 만들고 모두 받아 씀」**을 실시간 작업 앞 전제로. +- B06 쪽은 다시 셈이 덮어 쓴 `detail.longitudinal.design_profiles`(Cross_Refresh.ts:306)로 판정해 「안 낡음」 — 같은 순간 두 판정이 반대. + +## 5. 단계별 실시간 길 — 노선 한 번 바뀔 때(배수유역 빼고) + +| 차례 | 할 일 | 자리(계산 자리) | 예상 | +| --- | --- | --- | --- | +| 1 | 측점 목록 · 기하 | 가 sub1 | 가 몫 | +| 2 | 측점 지반선 표본 | 아 sub8 | 아 몫 | +| 3 | 전 측점 횡단 설계 | 브라우저 TS(① 짝 · 지금 그대로) | 0.09 s | +| 4 | 구조물 면적 · 유토곡선 | 브라우저 TS(② 짝) | 0.02 s | +| 5 | 보이는 카드 · 종단 · 유토곡선 그리기 | 브라우저 | 약 0.1 s | +| 6 | 흙 배분 | 서버 Node · 뒤에서 · 최신만 | +0.13 s(대기 0.4 s) | +| 7 | 3D 길 모형 | 웹 워커 · 3D 창 열렸을 때만 · 조작 멈춘 뒤 | +약 2 s(화면 안 멈춤) | +| 8 | [저장] · [확정] | 서버 정본(py 엔진 + Node) · 잠금 오버레이 | 2.2 s + 3D 서버 짓기 1~2 s | + +- 손에 닿는 시간 = 1 · 2 를 빼고 약 0.2 s · 나머지는 뒤에서. + +## 6. 규칙 바꿀 거리 + +- R1. 3D 저장본을 브라우저가 지어 PUT — 5장 「서버는 브라우저 값을 받아 적지 않음」과 어긋남 · 추천 = [저장] 때 서버 Node 가 짓기(규칙 그대로). +- R2. 측점 생성 · 지반 표본이 지금 ③ 서버 단독 — 노선 실시간이면 ① 짝 또는 ② TS→서버 Node 로 옮겨야 함(규칙 안 · 고르기만) · 가 · 아 와 함께 정함. +- R3. 노선이 [확인] 없이 실시간으로 바뀌면 초기값(initial_snapshot)을 쓰는 때 · [확인] 뜻 — 사 sub7 몫 · 여기선 「노선 바뀜 = 세션 초안 다 버림」(RouteEdit_Apply.ts:64)을 바꿔야 한다는 것만. + +## 7. 사용자에게 물을 거리 + +1. 노선이 바뀔 때 측점 고침 중 무엇을 넘기나 — 추천: 지금 일곱(지반 유형 · 측구 종류 · 측구 선택 · 2단 경사 · 암 경계 · 암 경사 · 소단) + 구조물 측점 조정은 구조물 따라 · 단면 유형 · 측구 방향은 새 지형이 정함. +2. 노선이 짧아져 사라진 측점의 고침 — 추천: 버리되 「노선 밖으로 나간 고침 N 건」 한 줄 알림. +3. 3D 다시 짓는 때 — 추천: 3D 창이 열려 있을 때만 · 조작 멈춘 뒤 1 s 자동 · 닫혀 있으면 안 지음. +4. 횡단 카드는 보이는 것 먼저 · 나머지는 뒤에 그려도 되나 — 추천: 예. +5. [전체 측점 반영]이 측점마다 지금 값을 「사용자 선택」으로 박는 동작을 없애도 되나(표준만 반영) — 추천: 예. +6. 다시 셈 뒤에도 낡은 측점이 남을 때 — 추천: 곡선은 그리고 그 측점만 표시(지금은 「새 값만 보여주기」로 곡선을 숨김). +7. 유토곡선 머묾(계획선 두 벌)을 실시간 작업 앞에 따로 먼저 고치나 — 추천: 먼저(S · 실시간의 전제). diff --git a/docs/raw/조사/2026-10-16_341_부록3_배수유역.md b/docs/raw/조사/2026-10-16_341_부록3_배수유역.md new file mode 100644 index 000000000..0572ff996 --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록3_배수유역.md @@ -0,0 +1,172 @@ +# 341 다 · 배수유역 — 실시간 연동 방향 검토 (요구 231 의 6 · 7번 · 읽기만) + +- 창: sub3(Opus 5.5) · 2026-10-16 · 코드 · 마스터 · 계획서 안 고침 · 커밋 없음. +- 실측: 검증_sub3(`1f93a515…`) 도엽 · 노선 · 서버 코드를 그대로 부름(저장 안 함) · 스크립트 `tmp/341/bench_ws.py` · 원자료 `tmp/341/bench_result.json` · `tmp/341/bench.log`. +- 실측 조건: 랩탑에서 다른 창 여럿이 동시에 도는 중 → 같은 계산이 340 보다 약 2 배 느림(기준 137 s · 340 은 60 s). **비율과 「결과가 같은가」만 믿을 것** · 아래 「예상 시간」은 340 기준으로 환산한 값. + +## 한 줄 결론 + +- 배수유역 60 s 의 몸통은 「흐름 방향 다시 만듦 + 도로 닿음 판정을 파이썬 한 칸씩 돌림」. **흐름 방향은 한 번만 짓고, 판정은 한꺼번에(벡터) 하면 결과가 한 칸도 안 바뀌고(실측 차이 0 셀) 60 s → 약 12~15 s · 흐름 방향까지 영구저장하면 약 4~6 s.** +- 배수유역 결과는 **평면(노선)과 관 자리에만** 따름. 종단 계획고 · 횡단 조작은 결과를 안 바꿈. +- 가장 큰 막힘 = 노선 [확인] 체인이 「배수유역 → 관 자리 → 관에 맞춘 종단 계획선」 차례로 묶여 있음. 관 기본 자리는 배수유역 없이도 바로 나옴(세류선 × 노선) → 이 고리를 끊으면 수동 모드가 성립. + +--- + +## 1. 지금 — 언제 돌고 누가 쓰나 + +### 1-1. 큰 계산(격자 해석 · 340 기준 60 s)이 도는 때 + +| 때 | 자리(파일:줄 · 함수) | 저장분 쓰나 | +| --- | --- | --- | +| 자동설계 체인(파일 올린 뒤 처음) | `B03_FileInput_Service_Chain.py:67` `_prepare_drainage_pipes_and_reprofile` → `:92` `get_primary_region(refresh=False)` | 저장분 없으면 계산 | +| 노선 [확인](노선 편집 창) | 화면 `B05_Profile_UI_RouteEdit_Apply.ts:89` `replanRoute` → `B05_Profile_Router_Replan.py:357` 관 지점 지움 → `:428` `run_redesign_chain` → `B03_FileInput_Service_Chain.py:574` `refresh=True` | 무조건 다시 | +| B04 [유역 다시 분석] 단추 | `B04_PreProcess_UI_Watershed.ts:544` `refresh=true` | 무조건 다시 | +| 지표면 확정 뒤 체인 | `B04_PreProcess_Router.py:265` | 체인과 같음 | +| 계산 본체 | `B04_PreProcess_Router_Watershed.py:372` `get_primary_region` → `B04_PreProcess_Engine_Watershed_Analyze.py:151` `preview_stages` → `B04_PreProcess_Engine_Watershed_Expand.py:114` `expand_by_red_boundary` | 결과는 `drainage/00_watershed_response.json` + 격자 배열(npz) | + +### 1-2. 작은 계산(세부 유역 다시 나눔 · 0.2~0.3 s · 격자 해석 없음) + +| 때 | 자리 | +| --- | --- | +| B05 · B06 배수유역 칸 열기(세션 초안 있으면 POST · 없으면 GET) | `B05_Profile_UI_Drainage_Panel.ts:421` `loadSaved` ← `design_profile.ts:208` · `:688` | +| 관 더함 · 옮김 · 지움 · 되돌리기 · 시설 바꿈 · 구조물 폼에서 관 추가 | `B05_Profile_UI_Drainage_Panel.ts:149-152` → `analyze()` `:435` (`:607` · `:642` · `:623`) | +| [유역 다시 나누기] · [배관 배치 초기화] | `:438` · `:431`(DELETE) | +| [저장] · [확정] | `design_shared.ts:302` → `savePipes` PUT `:672` | +| 서버 쪽 | `B04_PreProcess_Router_Basins.py:357` `_resolve` → `common_util_drainage_detail.py:175` `build_detail`(저장된 격자 배열을 읽어 관마다 나눔) | + +### 1-3. 안 도는 때 + +- 계획고 ▲▼ · 종단 고침 · 횡단 고침 · 유토곡선 — 배수유역에 안 닿음(입력이 아님). +- 배수유역 입력 = 노선 평면 정점 · 도엽 등고선 · 세류선 · 관 자리 · 노선 정점 z 의 최저값(등고선 하한 = 최저 − 10 m · `B04_PreProcess_Engine_Watershed_Grid.py:554`). + +### 1-4. 결과를 쓰는 곳 + +| 쓰는 것 | 자리 | 비고 | +| --- | --- | --- | +| 관경 **자동 지정** | `B04_PreProcess_Router_Basins.py:179-209` `_apply_recommendations` | 사용자가 안 만진 관 · 빈 칸에만 · **시설 종류도 BOX암거 · 세월교로 바꿈**(`:197-201`) | +| 새 관 기본값 · 보호공 높이(관경 + 0.5) · 세월교 월류 높이(설계유량) | `:105-142` `_apply_new_defaults` | 추천 **뒤에** 돎 — 추천이 이김 | +| 관경 **제안**(보여만 줌) | `B05_Profile_UI_Drainage_Parts.ts:121-153` 「Ø→Ø 배관 제안」 | | +| 관 자동 자리(간격 보충) | `common_util_drainage_detail.py:388` `place_pipes` → `:449` `_best_position`(흐름 세기 + 오목 지점) | 기본 관 = 노선 × 세류선 `Analyze.py:331` `_base_pipes` — **격자 해석 없이 나옴** | +| **종단 계획선**(관 자리에 맞춤) | 체인 3단계 `B03_FileInput_Service_Chain.py:115-124` `regenerate_sections` | 관 자리가 계획선 변화점 → [확인] 체인이 배수유역을 기다리는 까닭 | +| 유역도 · 화살표 · 세기 곡선 · 유입 집중점 | `B05_Profile_UI_Drainage_Panel.ts:339` `apply()` · B04 `B04_PreProcess_UI_Watershed.ts:494` | | +| 최소 덮개 경고 · 구조물 폼(세월교 높이) · B06 종단 | `design_profile.ts:176-188` · `B05_Profile_UI_Structures_Panel.ts:591` · `B06_Section_UI_Section_View_Profile.ts:224` | `onPipesChanged` 로 받음 | +| B06 배관 횡단도 세트 | `B06_Section_Engine_Culvert.py:618` | 관경 빈칸이면 세트 건너뜀 | +| B07 CAD 유역도 · B08 수량 | `B07_DesignDetail_Engine_Cad_Basin.py` · `B08_Quantity_Summary_Table.ts:147` | | + +### 1-5. 지금 구조의 흠(실시간에 걸림) + +- 저장된 배수유역 응답에 **노선 지문이 없음** — 노선이 바뀌어도 스스로 모름(`B03_FileInput_Service_Chain.py:90` 주석). 낡음 표시를 못 함. +- 노선만 바뀌고 큰 계산을 안 돌리면, 세부 유역 나눔(`build_detail`)이 **옛 노선의 격자 배열 + 새 노선 정점**을 섞어 씀 → 틀린 유역. 지금은 [확인]이 늘 큰 계산을 돌려 드러나지 않음. +- 서버 계산이 요청 하나에 묶여 끝까지 감(취소 없음) · 화면은 `requestSeq`(`Drainage_Panel.ts:183` · `:384-397`)로 늦은 응답만 버림. + +--- + +## 2. 6번 — 관경 자동 지정 끄기 · 기본 1000 φ + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 관경 자동 지정 | `B04_PreProcess_Router_Basins.py:202-207` `_apply_recommendations`(py) — 유역 유량으로 800~1500 골라 빈 칸에 넣음 | 관경 넣는 줄을 뺌 → 뒤따르는 `_apply_new_defaults` 가 마스터 기본값으로 채움 | py 1 + 시험 2~3(`test_b05_drainage_recommend.py` · `test_b04_pipe_points_facility.py`) | 새 관 = 1000 고정 · 배수유역 결과 없이도 관 값이 정해짐 | 설계유량이 큰 유역도 1000 — 제안 표시로만 알림 | S | +| 시설 종류 자동 바꿈(배관 → BOX암거 · 세월교) | 같은 함수 `:197-201` | 같이 끌지 사용자에게 물음(물을 거리 1) — 끄면 늘 배관으로 시작 | 같은 파일 | 배수유역 결과와 관 정본이 완전히 떨어짐 | 큰 유역에 배관 1000 이 남음 — 제안으로 보완 | S | +| 기본값 1000 | **이미 1000** — M02 마스터 `resources/master_template/구조물정의.json:60`(배관) · `:551`(세월교 안 관) · 화면 빈칸 대체값도 1000(`B05_Profile_UI_Profile_MinCover.ts:39` · `common_util_culvert_sets.ts:244` · `B06_Section_Engine_Culvert.py:283`) | 바꿀 것 없음 | 0 | — | 마스터 바꾸면 M02 에서 사용자가 고침 | — | +| 하한 800 | `config_system_design.py:240` `PIPE_DEFAULT_DIAMETER_MM=800` — 추천 하한(별표2 예외)만 · 화면 `config_frontend.ts:176`(=800)은 안 쓰는 코드(`B05_Profile_UI_IrregularStations.ts:497`)만 씀 | 그대로(제안의 하한) · 이름이 「기본」이라 헷갈림 — 이름만 바꿀지는 별건 | 0~2 | — | 이름 헷갈림 | S | +| 이미 놓인 관 | `pipe_points.json` 에 추천값(800 · 1200 …)이 이미 들어 있음 · 사용자 관은 원래 안 건드림 | 추천: **그대로 둠**(물을 거리 2) · 바꾸려면 일괄 1000 이관 도구 | 0(또는 이관 1) | — | 이관하면 저장된 설계가 바뀜 → 보호공 높이 · 수량 연쇄 | S | +| 관경 제안(보여만 줌) | 응답 `recommended_diameter_mm` · `Drainage_Parts.ts:121-153` | 그대로 남김 · 배수유역이 낡으면 제안 옆 「낡음」 | ts 1 | 사용자가 보고 고름 | 수동 모드에서 오래 낡을 수 있음 | S | + +--- + +## 3. 7번 — 설정 창 자동/수동(기본 수동) + +### 3-1. 지금 있는 것 + +- 설정 **모달은 없음**. B05 왼쪽 「페이지 설정」 칸(`B05_Profile_UI_Panel_Settings.ts:30-232`)만 있음 · B06 은 칸 둘(`B06_Section_UI_Page_Panel.ts:48` · `:60`). +- 모달 틀은 있음 — `ui_template_modal.ts:27` `openModal`. +- 설정 저장 자리: 계정 화면 설정 `aislo:pref:*` → `/api/dashboard/me/ui-prefs`(`b_page_state.ts` 약 `:339-400`) · 페이지 상태는 세션(`b_page_state.ts:216`). +- 흐림 덮개(데이터 상태용)는 없음 · 진행 표시 `createProgressCircle`(`ui_template_progress.ts:34` · 이미 `B05_Profile_UI_Drainage_Chrome.ts:111` 에서 씀) · 늦은 응답 버림 `requestSeq`(`Drainage_Panel.ts:183`). +- `B05_Profile_UI_Drainage_Panel.ts` 가 **딱 700 줄** — 흐림 · [업데이트] · 세대 번호는 새 파일로 나눠야 함. + +### 3-2. 안 + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 설정 창 · 자동/수동 칸 | 없음 | B05 · B06 머리에 ⚙ → `openModal` 에 「배수유역 계산: 수동(기본) / 자동」 · 저장은 계정 화면 설정(`aislo:pref:drainage-mode`) | ts 2~3 | 사람마다 기억 | 프로젝트마다 달리 둘지(물을 거리 3) | S | +| 계산 부르는 것(입력) | 서버가 **저장된 노선 파일**을 읽음(`B04_PreProcess_Router_Watershed.py:167` `_prepare` → `load_design_route`) — [저장] 전 노선은 못 셈 | 새 요청 「지금 노선으로 셈」 — 몸통에 노선 정점 + 세대 번호 · 서버 단독(③) 계산 · **작업본에 안 씀**(답으로만 돌려줌) | py 2 · ts 1 | [저장] 전 노선으로 셈 | 데이터 3층 — 조작 중 결과는 캐시(세션)에만 · 아래 「규칙 바꿀 거리」 | M | +| 자동 = N 초 조용하면 | 없음 | 평면(노선) · 관 자리가 바뀐 뒤 N 초 아무 조작 없으면 보냄 · 결과는 배수유역 칸만 조용히 바꿈 · 덮개 없음 | ts 1~2 | 조작 안 막음 | **종단 · 횡단 조작은 결과를 안 바꿈** → 그걸로 다시 시작하면 헛수고(물을 거리 4) · N 은 계산 시간에 맞춰 3 s 추천(물을 거리 6) | S | +| 수동 = 흐림 + [업데이트] | 없음 | 입력(노선 지문 · 관 자리)이 낡으면 배수유역 칸만 흐림 + 가운데 [업데이트] · 누르면 그때 입력으로 보냄 · 결과 오기 전엔 칸 구석에 「계산 중」 표시(진행 원 재사용) · 다른 칸 · 조작은 그대로 | ts 2(새 파일 1) · css 1 | 배수유역이 조작을 안 막음 | 낡은 유역 위에 관을 더하면 세부 유역 나눔(0.2 s)도 낡은 격자를 씀 → 흐림 동안 세부 나눔도 멈춤 | S | +| 다시 조작하면 처음으로 | 늦은 응답만 버림(`requestSeq`) · 서버는 끝까지 셈 | 화면: 세대 번호 + `AbortController`(지금은 시간 초과용만 · `B04_PreProcess_Api_Fetch.ts:155`) · 서버: 프로젝트별 「마지막 세대」 기록 → 계산 단계 사이(확장 회차마다)에서 세대가 바뀌었으면 그만둠 · 늦은 답은 지문이 지금과 다르면 버림 | py 1~2 · ts 1 | 헛계산 줄임 · 화면은 늘 마지막 조작 기준 | 파이썬 스레드는 억지로 못 끊음 — 단계 사이 확인뿐(빠른 길 뒤엔 4~6 s 라 거의 무의미) | S~M | +| 낡은 값 표시 | 응답에 노선 지문 없음 | 응답 · 저장분에 노선 지문 + 관 자리 지문을 찍음 → 화면이 지금 노선과 비교해 「낡음」 · 세부 유역 나눔도 지문이 다르면 나누지 않고 「낡음」을 돌려줌 | py 2 · ts 1 | 틀린 유역을 안 보임 | 옛 저장분(지문 없음)은 「낡음」으로 봄 — 열 때 한 번 흐림 | S | +| [저장]과의 관계 | [저장] = 관 지점 PUT(`design_shared.ts:302`) · 배수유역 큰 계산은 [확인] 체인에서만 | 추천: 빠른 길(4장) 들어온 뒤엔 **[저장] 안에서 서버가 정본으로 다시 셈**(4~6 s · 저장 덮개 안) · 그 전엔 「배수유역 낡음」 표시를 달고 저장(관 자리 · 관경은 정본대로 저장) | py 1~2 · ts 1 | [저장] 뒤엔 늘 맞는 유역 | 빠른 길 전엔 [저장]이 60 s 늘어남 → 낡음 표시가 현실적(물을 거리 5) | M | +| [확인] 체인의 배수유역 기다림 | `B03_FileInput_Service_Chain.py:574` 배수유역(60 s) → 관 자리 → 계획선 | 관 기본 자리 = 노선 × 세류선(`_base_pipes` · 격자 없음) + 간격 보충은 **오목 지점만**으로 바로 → 계획선 · 배수유역은 수동이면 낡음 · 자동이면 뒤에서 | py 2 | [확인] 76 s → 약 10~16 s(340 의 「배수유역 뺀 나머지 6~10 s」+ 관 자리) | 간격 보충 관 자리가 지금(흐름 세기 반영)과 몇 m 달라짐 · 나중에 배수유역이 와도 관 자리는 안 옮김(물을 거리 8) | M | + +--- + +## 4. 60 s 줄일 길 — 실측 근거 + +### 4-1. 실측(검증_sub3 · 붐빈 랩탑 · 340 의 약 2 배 느림) + +| 잰 것 | 값 | 뜻 | +| --- | --- | --- | +| 지금 방식 전체(`preview_stages`) | 137.1 s(1차 영역 33.4 · 확장 103.4) · 확장 9 회 · 최종 격자 1095×1235 · 적색 460,035 셀 | 340(60 s)의 약 2.3 배 — 붐빈 탓 | +| 확장 회차마다 | 4.2~13.4 s · 방향장 새로 만든 회차가 2 배 | 7 번이 방향장 새로 | +| 흐름 방향 한 번(최종 격자) | 7.7 s | 지금은 이걸 8 번 함 | +| 흐름 방향 한 번(최종 + 사방 100 m) | 9.9 s | 넉넉히 지어도 비용 조금 | +| 흐름 방향 저장 · 읽기 | 0.04 s · 0.02 s · 20 MB(압축 안 함) | 영구저장 값어치 큼 | +| 저장한 흐름 방향으로 한 회차 | 4.0 s — 결과 **같음** | 남은 시간 = 도로 닿음 판정 | +| 도로 닿음 판정 지금(파이썬 한 칸씩) | 4.4 s / 회 | 10 회면 340 의 22 s | +| 도로 닿음 판정 한꺼번에(포인터 건너뛰기 · numpy) | **0.22 s** · 지금 판정과 **차이 0 셀** | 20 배 | +| 확장 고리 없이 최종 격자 통째 한 번 | 0.37 s · 기준 적색과 **차이 0 셀** | 고리 결과와 같음 | +| 넉넉한 격자(사방 +100 m) 통째 한 번 | 0.22 s · 안쪽 차이 0 · 바깥 적색 0 | 고리가 일찍 멈춘 곳 없음 | + +### 4-2. 안 + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일 | 효과(340 기준 환산) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| A. 흐름 방향 한 번 짓기 | `Expand.py:132` 처음 여유 = 띠 2 겹(100 m) · 격자가 커질 때마다 `Descent.py:247` `build_contour_descent` 다시(8 회 · 30 s) | 처음 여유를 넉넉히(예 400~600 m) 또는 커질 때 「큰 격자에서 잘라 씀」 → 한 번만 | py 1 | 30 s → 4~5 s | 넉넉한 격자 가장자리 값이 지금과 미세하게 다를 수 있음(이번 땅은 0 셀) · 다른 땅(S자 등) 골든 대조 | S | +| B. 도로 닿음 판정 한꺼번에 | `Flow.py:300` `classify_flow` → `:394` `_walk_from`(파이썬 반복 · 회당 1~2.7 s · 10 회 22 s) | 같은 규칙을 포인터 건너뛰기로(이미 같은 방식 `Flow.py:140` `trace_flow` 있음) | py 1 + 거울 시험 1(지금 판정과 칸마다 같음) | 22 s → 0.5 s 안 | 기록용 숫자(최외곽 출발 · 내부 보충 셀 수)는 사라짐 — 로그만 | S | +| A+B 합 | 확장 53 s | | py 2 | **배수유역 60 s → 약 12~15 s** · [확인] 76 s → 약 28 s(3장 체인 끊기 없이) | | S | +| C. 흐름 방향 영구저장 | 없음(메모리 캐시는 등고선 읽기 `Descent.py:70` 만) · 격자 원점 = **도로 시작점**(`Grid.py:229` · 07-31 사용자 지시) | 전처리 끝(도엽 합친 뒤)에 노선 둘레 넉넉한 범위로 한 번 지어 `drainage/descent_<지문>.npz` 저장 · 지문 = 도엽 등고선 + 남긴 등고 단(하한) + 격자 원점 · 셀 · 범위 · 노선이 범위 안이면 읽기만(0.02 s) | py 2~3 | A 의 4~5 s → 0.1 s · **배수유역 약 4~6 s** | 원점이 도로 시작점이면 시작점이 움직일 때마다 버려짐 → 원점을 **좌표 정수 m(프로젝트 공통)** 로 바꿔야 함(규칙 바꿀 거리 2 · 물을 거리 7) · 노선 최저 z 가 등고 단을 넘으면 다시 지음 · 파일 20~40 MB/벌 | M | +| D. 확장 고리 없앰 | 고리 10 회(`Expand.py:146`) | C 의 큰 격자에서 판정 한 번 · 적색 = 유역 | py 1~2 | B 뒤엔 회당 0.4 s 라 이득 4 s 안팎 | B04 화면의 「파랑(안 닿는) 칸」 범위가 바뀜(지금은 고리가 넓힌 영역만) · 그림 맞춰 봄 | M · 미룸 추천 | +| E. 도엽 읽기 · 좌표 바꿈 | `Router_Watershed.py:167` `_prepare` — 피처 4,200 개를 매번 읽고 재투영(3.8 s · 이번 7.9 s) | 프로젝트 좌표로 바꾼 등고선을 한 번 저장해 읽음 | py 1 | 3.8 s → 0.3 s | 도엽 · 좌표계 바뀌면 지움(지문) | S | +| F. 1차 영역 | `Analyze.py:84` `resolve_primary_region` 2.6 s(이번 33.4 s — 붐빈 탓인지 따로 확인 거리) | 그대로 | 0 | — | 이번 값이 유독 큼 — 혼자 돌 때 다시 잴 것 | — | +| G. 응답 · 저장 | 1.0 s · 1.27 MB JSON | 그대로 | 0 | — | — | — | + +### 4-3. 줄인 뒤 예상(340 기준) + +| 단계 | 지금 | A+B | A+B+C+E | +| --- | --- | --- | --- | +| 도엽 읽기(`_prepare`) | 3.8 | 3.8 | 0.3 | +| 1차 영역 | 2.6 | 2.6 | 2.6 | +| 흐름 방향 | 29.6 | 4~5 | 0.1 | +| 도로 닿음 판정(10 회) | 22.3 | 0.5 | 0.5 | +| 그 밖(굽기 · 세기 · 외곽 · 저장) | 2 | 2 | 2 | +| **합** | **60** | **약 13** | **약 5.5** | + +- 자동 모드 N 초는 계산 4~6 s 에 맞춰 3 s 면 조작 멈춘 뒤 10 s 안에 유역이 바뀜. + +--- + +## 5. 규칙 바꿀 거리(CLAUDE.md 5장 · 사용자 지시와 부딪힘) + +1. **조작 중 서버 계산 결과의 자리** — 「지금 노선으로 셈」 답은 작업본(`00_watershed_response.json` · 격자 배열)에 안 쓰고 화면 캐시(세션)에만 둠 · [저장] 때 서버가 정본으로 다시 셈 → 5장 안에서 됨. 다만 응답 1.27 MB + 세부 유역 나눔에 격자 배열이 필요 → 세부 나눔(0.2 s)도 같은 요청에서 같이 돌려줘야 함(격자를 화면에 안 넘김). 서버에 「후보」 보관을 두려면 규칙 추가가 필요 — 추천은 안 둠(C 뒤엔 다시 셈이 수 초). +2. **격자 원점 = 도로 시작점(2026-07-31 사용자 지시 · `Grid.py:229`)** — 흐름 방향 영구저장(C)에는 좌표 정수 m 고정 원점이 필요. 지시의 뜻(셀이 제자리에 남음)은 더 잘 지켜짐. +3. 잠금 덮개 — 배수유역 계산엔 안 씀(조작 막지 않음) · [저장] 안 다시 셈만 [저장] 덮개 안 → 5장 그대로. + +## 6. 사용자에게 물을 거리 + +1. 관경 자동 지정을 끌 때 **시설 종류 자동 바꿈(배관 → BOX암거 · 세월교)도 끌지** — 추천: 같이 끔 · 제안으로만 보임. +2. **이미 놓인 관**의 관경(추천으로 들어간 800 · 1200 …) — 추천: 그대로 둠 · 새 관만 1000. +3. 자동/수동 설정을 **사람마다(계정) 또는 프로젝트마다** — 추천: 계정. +4. **종단 · 횡단 조작도** 배수유역을 다시 셈 · 처음으로 되돌림 대상인지 — 결과가 안 바뀜 · 추천: 평면(노선) · 관 자리만. +5. 배수유역이 낡은 채 **[저장]** 하면 — 추천: 빠른 길(A+B) 뒤엔 [저장] 안에서 서버가 다시 셈 · 그 전엔 「낡음」 표시를 달고 저장. +6. 자동 모드 **조용한 시간 N** — 추천: 3 초. +7. 흐름 방향 영구저장을 위해 **격자 원점을 도로 시작점 → 좌표 정수 m 고정**으로 바꿔도 되는지 — 추천: 바꿈. +8. [확인] 때 **관 자리를 배수유역 없이 먼저**(노선 × 세류선 + 간격 보충은 오목 지점만) 정하고, 배수유역이 나중에 와도 관 자리는 안 옮기는 것 — 추천: 그렇게. +9. 수동 모드 흐림 범위 — 추천: **배수유역 칸만**(유역도 · 세부 유역 목록 · 관경 제안) · 종단 그림의 관 표시는 그대로. + +## 7. 차례 추천 + +1. A+B(흐름 방향 한 번 · 판정 한꺼번에) — 결과 같음 · 60 s → 13 s · 화면 안 바뀜 · 먼저. +2. 6번(관경 자동 지정 끔) — 줄 몇 개. +3. 응답에 노선 지문 · 낡음 판정. +4. [확인] 체인에서 배수유역 떼기(관 자리 먼저). +5. 설정 창 · 자동/수동 · 흐림 + [업데이트] · 세대 번호 — 노선 편집이 B05 본문으로 온 뒤(갈래 가 · 마 · 사와 맞춤). +6. C · E(영구저장) — 물을 거리 7 정한 뒤 · 갈래 라(영구저장)와 같은 틀로. diff --git a/docs/raw/조사/2026-10-16_341_부록4_영구저장.md b/docs/raw/조사/2026-10-16_341_부록4_영구저장.md new file mode 100644 index 000000000..bd9fe7596 --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록4_영구저장.md @@ -0,0 +1,149 @@ +# 341 라 · 영구저장 — 매번 다시 계산 · 다시 받는 것 전수 (요구 231-2 · sub4 · 읽기만) + +- 범위: B03 · B04 · B05 · B06 서버 API + 브라우저 계산 · 코드 수정 없음 · 서버 안 띄움(코드 읽기 + 340 측정값 + 검증_sub4 storage 파일 크기). +- 시간 근거: `docs/raw/조사/2026-10-16_340_계산시간_측정.md`(아래 「340」). +- 줄 번호는 sub_laptop_4 현재 판(dev 받은 뒤). + +## 결론 한 줄 + +- 저장본이 아예 없거나(도엽 3D 면 37 s · 3D 길 모형 · 세부 유역 · 횡단 상세 · 유토 배분) 열쇠가 약해(배수유역 · 도엽 병합) 같은 계산을 되풀이 · 고칠 틀은 이미 코드 안에 있음(비용면 서명 · 추천 노선 열쇠 · B07 덧그림 기억 · ETag 도우미) — 「입력 지문 열쇠 + 결과 파일 한 쌍」 하나로 통일하면 됨. +- 가장 큰 막힘 = 배수유역 60 s(열쇠 = 형식 번호뿐 · 노선 [확인]마다 무조건 다시) — 다 sub3 몫 · 여기선 목록만. +- 그다음 = B03 같은 파일 다시 올림 → B04 폴더 통째 지움 → 전처리 246 s 다시 · B04 화면 113 MB 매번 다시 받음. + +## 1. 전수 표 + +크기 = S(파일 1~2 · 반나절) · M(파일 3~6) · L(여러 페이지 · 설계 결정 필요). 효과 시간은 340 값 기준 · 「추정」은 안 잰 값. + +### 1-1. 전처리 · 파일 입력 (B03 · B04 서버) + +| # | 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일 | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| R1 | 도엽 등고선 3D 면(sheet laplace) | py · `B04_PreProcess_Engine.py:276-290` 이 매 전처리 무조건 `build_sheet_surface_from_route` 부름 → `Engine_SheetSurface.py:475-500` · `:406-472` 저장 검사 없음 · 무조건 씀(`:368` `:379` `:380`) · `POST /surface/sheet-surface` 도 「있으면 그대로」라 적고(`Router_GIS.py:320`) 무조건 지음(`:338`) · **38 s / 다시 37 s** · 결과 방식당 약 50 MB(npz 5.6 + glb 18.9 + smooth 6.1 + glb 18.9) | 결과 옆 열쇠 파일(`dtm_sheet_{m}.key.json`) · 열쇠 = 도엽_등고선.geojson 이름:mtime:크기 + 노선 서명 + CRS + `SHEET_SURFACE_GRID_M`·`MARGIN_M`·smoothing 설정 + scene_bounds + ALGO 번호 · 같으면 건너뜀 · 비용면 서명(`B05_Profile_Engine_Solver.py:169-175`) 틀 그대로 | 3 (SheetSurface · Engine · Router_GIS) | 전처리 다시 44 s → 약 7 s · POST 다시 37 s → 0 | 노선 서명 넣을지 — 도엽 3D 면 범위가 B03 노선 기준(`load_design_route`) · 노선 바뀌면 범위 바뀜 · 시험 = 같은 입력 두 번째 0 s | S | +| R2 | 지표면 모델 DB 행 지우고 다시 넣음 | py · `B04_PreProcess_Repository.py:340-369` `delete_project_surface_models` → 다시 INSERT · 모델 id 매번 바뀜 → 화면 주소(`/models/{id}/preview` · `/contour`) 바뀜 → 브라우저 IndexedDB 열쇠 · ETag 빗나감 · `routes.surface_model_id` FK SET NULL 로 노선 연결도 끊김 | (필터 · 방식 · smooth) 기준 UPSERT 로 id 유지 · 파일 안 바뀌면 행도 그대로 | 1~2 (Repository · 부르는 Engine) | 전처리 다시 뒤 첫 B04 · B05 열기 약 38~83 MB 다시 받기 없앰 | routes 연결 끊김이 의도인지(새 지표면이면 끊는 게 맞음) — 파일 지문 같을 때만 유지 · `terrain_layers` CASCADE 확인 | M | +| R3 | 같은 파일 다시 올림 → B04 통째 지움 | py · `B03_FileInput_Router_Chunks.py:106-120` 지문 같아 전송 건너뛰어도 `_complete_file_input_if_ready` → `Router_Helpers.py:244` `purge_project_outputs` → `common_util_project_reset.py:44-54` B04_PreProcess 통째 rmtree(structured.npz 841 MB · 배수유역 저장본 포함) · 초기값도 버림(`:243`) · **246 s 다시** | 지문(B03 · 크기 + 앞·가운데·끝)과 `processed/source_identity.json` 이 같으면 B04 결과 남기고 단계 표시만 되돌림 · 「처음부터 다시」는 따로 고름 | 2 (Router_Helpers · Router_Chunks) | 같은 파일 재올림 246 s → 약 7~44 s | 사용자 뜻 — 지금은 [바꾸기 확인] 창(`confirm_replace`) 뒤 지움 · 같은 파일 재올림 의도가 「처음부터」일 수 있음 → 물을 거리 1 · 지문은 일부 바이트라 같은 크기 다른 내용 드묾(앞·가운데·끝 24 MB) | M | +| R4 | 다시 돌 때 점군 통째 풀기 | py · `B04_PreProcess_Engine.py:181-196` 저장본 다 맞아도 `structured.npz`(841 MB 압축) xyz 를 풀어 점 수 · 평균 높이만 셈 · **다시 7 s** | 점 수 · 평균 Z · bounds 를 `source_identity.json` 또는 models/manifest 에 함께 적고 읽음 | 1~2 | 7 s → 0 | 마스크 만들 때 점 수 대조(`Engine.py:208-212`)도 저장값으로 | S | +| R5 | 도엽 병합 · 국가 GIS 벡터 열쇠 약함(값이 낡음) | py · `Engine.py:437-439` 도엽_*.geojson 하나라도 있으면 건너뜀(고른 도엽 목록 무시) · `Engine.py:388-393` bounds 파일 있으면 건너뜀(범위 무시) | 열쇠 = 도엽 번호 목록 · 범위 · 같으면 건너뜀 · 다르면 다시 | 1 | 시간보다 바른 값 — 노선이 도엽 밖으로 나가면 지금은 옛 병합본 씀 | 다시 만들면 R1 · 배수유역 열쇠도 따라 바뀜(연쇄 정상) | S | +| R6 | 배수유역 큰 계산(primary-region) | py · `Router_Watershed.py:227-245` 저장분 검사 = `schema_version` 만 · 노선 [확인] 체인 `Service_Chain.py:574` `refresh=True` 무조건 · **60 s** · 저장분 읽기 0.10 s · 1.27 MB 를 매번 json 풀고 다시 묶음 | → **다 sub3** · 여기선 열쇠 후보만: 노선 서명(`route_signature` · `common_util_drainage_pipes.py:156-165` 이미 있음) + 도엽 등고선 · 하천 mtime + 지표면 설정 + 형식 번호 · 노선 같으면 건너뜀 | (sub3) | (sub3) | 흐름 방향(02_flow_direction.npz) 재사용 범위 = sub3 | (sub3) | +| R7 | 지도 타일 메모리 기억 낡음 | py · `B04_PreProcess_Engine_MvtHelper.py:22,41-55` GeoDataFrame 을 `{pid}_{layer}` 로 기억 · mtime 없음 → 전처리 다시 뒤 서버 재시작 전까지 옛 타일 | 열쇠에 파일 mtime · 크기 더함 | 1 | 시간 아님 — 바른 값 | — | S | +| R8 | LAS 두 번 통째 읽기 | py · `B03_FileInput_Engine_Analyze.py:201` 올림 때 분류 세기 한 바퀴 + 구조화가 또 한 바퀴 | 분류 세기를 구조화 안에서 · 메타는 나중 채움 | 2 | 올림 1회만 · 약 10~20 s 추정(안 잼) | 올림 화면이 분류 수를 먼저 보여 주는지 확인 | M | + +### 1-2. B04 화면 (113 MB 매번) + +| # | 항목 | 지금 | 바꾸면 | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| R9 | 점군 27.8 MB | ts → py · `B04_PreProcess_UI_Page.ts:541` → `Api_Fetch.ts:247` 그냥 fetch · 서버 `Router.py:301-376` 요청마다 50만 점 무작위 표본(`rng.choice`) + `.tolist()` JSON · ETag 없음 · 브라우저 `response.json()` + Float32 채움 | 표본을 전처리 때 한 번 고정 이진 파일(Float32 · 약 6~8 MB 추정)로 저장 → `cached_file_response`(ETag) + `fetchCachedBytes`(IndexedDB) | 3 (Router · Api_Fetch · Viewer) | 27.8 MB → 0(304) · 파싱 수백 ms 줄음 | 무작위 표본이 매번 달라 보이는 게 지금 동작 — 고정 표본이면 같은 그림(문제 아님) · 필터 갈래마다 파일 하나 | M | +| R10 | IndexedDB 보관인데도 83 MB 다시 받음 | ts · `A00_Common/b_asset_cache.ts` — 저장 끝을 요청 `onsuccess` 로 봄(`:69` · 트랜잭션 `oncomplete` 아님) · 실패 조용히 삼킴(`:69-73` · `:140-142`) · 열기 `onblocked` 없음 · 실패 시 null 을 페이지 끝까지 기억(`:34` · `:49-50`) · `purgeOtherProjects` 가 열 때마다 모든 값을 읽음(`:98-104` · projectId 색인 `:46` 안 씀) | 트랜잭션 `oncomplete` 로 끝 판정 · 실패 한 줄 경고 · `onblocked`/`onversionchange` 처리 · 지우기는 색인 열쇠만 | 1 | B04 다시 열기 113 → 약 30 MB(R9 · R12 더하면 약 1 MB) · 3.8 s → 약 1.5 s 추정 | **원인 미확정** — 확인 거리 = B04 차가운 열기 직후 `aislo-asset-cache/assets` 열쇠 목록 · 저장 실패 경고 · 열기 막힘 | S | +| R11 | 등고선 주소 열쇠 어긋남 | ts · B04 · B11 미리받기 `...&recalculate=false`(`UI_TerrainViewer_Contours.ts:46` · `b_asset_cache.ts:379`) · B05 는 없음(`B05_Profile_UI_Viewer.ts:329` · `RouteEdit_Contour.ts:74-75`) → 같은 파일 두 벌 · B05 가 미리받기 못 씀 · 간격도 B11 `confirmed.contour_interval_m` 대 B05 `latest.surface_params` | 주소 만드는 함수 하나로 | 2~3 | B05 첫 열기 7~11 MB 덜 받음 | — | S | +| R12 | 꺼진 지도층도 다 받음 · 매번 다시 받는 층 | ts · `UI_MapViewer.ts:476-515` 9층 모두 처음에 받고 준비 · 도엽_등고선 36.8 MB 는 기본 꺼짐(`UI_MapLayers.ts:36-46`) · 지적도 · 행정구역 · 국가 등고선은 그냥 fetch + 서버 `json.loads` 다시 묶음(`Router_GIS.py:162-182`) ETag 없음 · primary-region 1.27 MB · pipe-points 103 KB 매번 | 꺼진 층은 켤 때 받음(→ 마 sub5 화면 배치와 겹침) · 남은 층은 파일 그대로 `cached_file_response` | 2~3 | 첫 열기 37 MB · 다시 열기 약 1.8 MB 줄음 | 물을 거리 3 | S | +| R13 | 3D 파싱 매번 | ts · GLB 두 벌 파싱(`UI_TerrainViewer.ts:430`) · B05 는 메모리 기억(`B05_Profile_UI_Viewer.ts:442-447`)인데 B04 는 없음 | 보류 — 새로고침 넘는 저장은 파싱된 배열 IndexedDB 저장이 필요 · 효과 작음(수백 ms) | — | 수백 ms | 3D 를 모달로 빼면(마 sub5) 열 때만 파싱 → 저절로 풀림 | — | + +### 1-3. B05 (노선 · 종단 · 배수 · 3D) + +| # | 항목 | 지금 | 바꾸면 | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| R14 | B05 첫 열기 세부 유역 POST 11번 | ts · 옛 소수 측점 관을 정수 m 로 옮기며(`B05_Profile_UI_Structures_Snap.ts:117-130` `snapOldStations`) 관마다 `movePipe` → `Drainage_Panel.ts:625-648` → `analyze()` → POST detail-basins · 옮긴 값은 세션 초안에만(`B05_Profile_Api_Pipes_Draft.ts:22-28`) → 세션 없으면 다음에도 또 · 서버는 11번 다 계산 | 옮기기를 한 번에 모아 POST 1번(B06 `snapOldPipes` · `B06_Section_UI_Page_Structures_Panel.ts:500-514` 틀) · 근본은 서버가 [저장] · 노선 [확인] 때 정수 m 로 정본에 씀 | 1~2 | 11 × 0.7~1.1 s 동시 → 1번 0.2~0.3 s | 정수 옮김이 정본에 안 들어가는 게 요구 167 의 뜻인지 | S | +| R15 | 세부 유역 · 관 지점 계산 매 요청 | py · `B04_PreProcess_Router_Basins.py:357-409` `_resolve` → `common_util_drainage_context.py:70-136`(DB 6번 + 노선 읽기 + DTM npz 읽기) → `build_detail`(`common_util_drainage_detail.py:175-234`) · 결과 저장 없음(GET pipe-points 도 매번 다시 셈) · 라우팅 npz 만 메모리 기억(`:237-286`) | (a) GET pipe-points = PUT 때 이미 쓰는 `04_detailed_basins.geojson` + 열쇠(관 목록 해시 + `route_signature` + 라우팅 npz mtime) 같으면 그대로 줌 (b) POST 도 같은 열쇠로 최근 몇 벌 기억 | 2 | 0.2~1.1 s → 0.05 s 안팎 추정 | 열쇠에 강우표 · 종단 Z(longitudinal) 넣어야 함 — 계획고가 바뀌면 관 깊이 바뀜 · 다 sub3 와 열쇠 맞춤 | M | +| R16 | DTM 표본기 npz 매번 읽음 | py · `common_util_surface_sampler.py:151-163` `build_surface_sampler` 기억 없음 · 체인 한 번에 4~5번 · 노선 편집 점 놓을 때 elevations · cross-preview · slope 요청마다(`B05_Profile_Router_Terrain.py:63-76`) | 프로세스 메모리 기억 · 열쇠 (경로 · mtime · 크기) — 라우팅 npz 기억(`common_util_drainage_detail.py:237-286`) 틀 그대로 | 1 | 요청당 수십~수백 ms 추정(npz 0.6~6 MB 풀기) · 노선 편집 실시간에 직접 닿음 | 메모리 = 지표면 몇 벌 수 MB · 서버 프로세스 하나 전제 | S | +| R17 | 종단 미리보기(profile-preview) 매번 비용면 · 하천 읽음 | py · `B05_Profile_Router_RouteInitial.py:365-398` → `load_terrain_and_streams`(`Engine_RouteInitial.py:114-138`) 비용면 npz + 하천 geojson 읽고 좌표 바꿈(여기선 하천 안 씀) · DB 2번 | 비용면 · 하천을 메모리 기억(`_POOLS` 틀 · 비용면 서명 열쇠) · 하천은 필요할 때만 | 1~2 | 점 놓기마다 수백 ms 추정 | — | S | +| R18 | 추천 노선 — 저장은 있음 · 맞아도 1.3 s | py · 저장 `B05_Profile/route_recommend/.json`(`Engine_RouteInitial_Store.py:72-73`) ✓ · 열쇠 만들려고 비용면 배열 통째 해시(`Engine_RouteInitial.py:375-386`) + 지형 · 하천 다시 읽음(`Router_RouteInitial.py:116-122`) · 지우기 없음(무한히 쌓임) | 열쇠 = 비용면 서명(npz 안에 이미 있음) + expected_route mtime + 하천 mtime + 설정 · 맞으면 파일만 읽음 · 종류당 최근 몇 벌만 둠 | 2 | 저장본 맞을 때 1.3 s → 0.05 s 추정 · 알약 누름 즉시 | 노선 [확인] 뒤엔 미리 셈 다시 안 함(체인만) — 지형 바꿈 뒤 첫 누름 52 s · 물을 거리 아님(사 sub7 · 마 sub5 단추 자리와 같이) | S | +| R19 | 3D 길 모형(코리도) — 브라우저가 짓고 서버는 받아 적기만 | ts · `B05_Profile_UI_Corridor_Build.ts:140` 주 스레드 1.6~2.0 s · 처음 GET 1.2 s + **PUT 15 MB 2.2 s**(`B05_Profile_UI_Corridor.ts:206-211`) · 서버 `B05_Profile_Router_Corridor.py:131-161` 해시 검산 없이 저장 · 서버 Node 판(`B05_Profile_Corridor_Prebuild.py:47-80`)은 자동 체인 끝만(`Service_Chain.py:322-330`) — 노선 [확인] 체인 · B06 [저장]·[확정] 엔 없음 → [확인] 뒤엔 `initial_corridor.json` 도 빠짐 · 자동 체인은 미리 지은 **뒤에** 서버 재계산 한 번 더(`:336-341`) → 미리 지은 것이 낡을 수 있음 | ② TS → 서버 Node: [확인] 체인 · [저장] · [확정] 끝에 `prebuild_corridor` · 자동 체인 순서 바꿈(재계산 → 짓기) · 브라우저 PUT 없앰 · 브라우저는 해시로 받기만 | 4~5 (Service_Chain · Router_Confirm · Router_Replan · Corridor.ts · Router_Corridor) | 3D 처음 1.9 s + 15 MB 올림 → 0(받기 15.6 MB · IndexedDB 뒤 0) · 저장 1~2 s 늘음(서버 짓기 1.0~1.9 s) | 해시 어긋남 — 브라우저 판은 초안 벽 · 구조물 면적(`B06_Section_Section_Store.ts:48-69`) · 로컬 재계산 설계를 넣음 → 서버 판과 다르면 「낡음」 판정 · 초안 있을 때만 브라우저가 짓기 → 물을 거리 4 | M | +| R20 | 측점 만들기 체인 한 번에 두 번 | py · `B05_Profile_Router.py:278` solve 안 + `B06_Section_Router.py:403` regenerate · 둘 다 `cross_*.json` 통째 지우고 다시 씀(`B05_Profile_Engine_Sections.py:498-504`) | 두 번째는 관 · 구조물이 바뀐 측점만 · 또는 첫 번째를 관 정한 뒤 한 번만(→ 가 sub1 체인 순서) | (sub1) | 약 1.5 s 추정 | 가 sub1 과 겹침 — 목록만 | M | +| R21 | 노선 편집 횡단 미리보기 — 전 노선 측점 만들고 하나 고름 | py · `B05_Profile_Router_Terrain.py:183-193` | 그 측점 둘레만 · (가 sub1 몫 · 계산 줄이기) | (sub1) | — | — | — | +| R22 | 열 때마다 받는 작은 것 | ts · `route/latest` 세션 있어도 뒤에서 다시(`B05_Profile_UI_Page_Latest.ts:54`) · `road-widths` · `surface/confirmed` · `route/structures` · `vworld-meta` · 구조 정의 판 버전 요청을 **기다린 뒤** 셋 받음(`B05_Profile_Api_Structures.ts:203-215`) · 합 21 요청 0.5 MB | 한 번에 묶는 「페이지 맥락」 요청 또는 버전 요청을 같이 보냄 → 사 sub7 한 페이지 상태와 같이 | 3~5 | 첫 열기 수백 ms 추정 · 횡단 보기 바꿈 왕복 하나 줄음 | 사 sub7 와 겹침 | M | + +### 1-4. B06 (횡단 · 유토곡선 · 확정) + +| # | 항목 | 지금 | 바꾸면 | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| R23 | [확정]·[저장] 서버 재계산 — 입력 지문 없음 | py · `B06_Section_Server_Calc_Prebuild.py:204-360` 전 측점 설계 다시(`Router_Design.py:281-338`) · Node · **정본 저장 0.7 s** = 바뀐 행 대조 없이 전 행 UPDATE(`Repository_Bulk.py:93-104`) · 같은 SELECT 세 번 · 자동 체인은 두 번 부름(`Router_Confirm.py:376` + `Service_Chain.py:336-341`) | (a) 입력 지문(측점 파일 mtime · DB 설계 · structures · pipe_points · 설정 · 번들 mtime) 같으면 Node 건너뜀 — B07 덧그림 기억(`B07_DesignDetail_Router_Support_Overlay.py:62-78`) 틀 (b) 바뀐 행만 씀 · SELECT 한 번 (c) 체인 두 번째 부름 지움 | 2~3 | [확정] 2.2 s → 약 0.8 s 추정 · 체인 1.3 s 줄음 | 서버 재계산은 「[저장]·[확정]은 서버가 정본으로 다시 계산」 규칙의 몸 — 건너뛸 땐 지문이 모든 입력을 덮는지 시험으로 확인 | M | +| R24 | Node 매번 새로 띄움 · 번들 낡음 검사 | py · `common_util_node_bundle.py:85-116` 부를 때마다 `subprocess.run(node …)` · 처음 0.75 s · 그 앞 `bundle_stale()`(`:43-64`) 가 `.ts` 약 330개 stat | 낡음 검사는 프로세스 시작 때 한 번(또는 폴더 mtime) · 상주 Node 는 계산 자리 일이라 보류 | 1 | 부름당 수십 ms 추정 · 유토 배분 첫 0.75 s 는 상주해야 풀림 | 개발 중 TS 고친 뒤 서버 재시작 필요 — 지침 표(백엔드 재시작)와 같음 | S | +| R25 | 유토 배분(haul-plan) 열 때마다 | ts → py · B05 · B06 열 때마다 POST(`design_profile_overlays.ts:43` 재생성 · 기억은 메모리뿐 `B05_Profile_Api_HaulPlan.ts:57-63`) · 서버 Node 매번 0.125 s(처음 0.75) · 저장된 `mass_haul.haul_plan_drawing`(마지막 재계산)은 B07 만 읽음 | 열 때는 저장된 haul_plan 을 열쇠(누가토적 해시) 맞으면 그대로 · 바뀔 때만 POST · 서버도 같은 열쇠로 기억 | 2~3 | 열기 0.13~0.75 s 줄음 | **나 sub2**(유토곡선 머묾 까닭)와 같은 자리 | S | +| R26 | 횡단 상세(sections/{route}/detail) 1.51 MB | py · `B06_Section_Router.py:253-337` 요청마다 측점 파일 66개 + longitudinal + 관 · 구조물 파일 읽고 형상 붙임 · **GET 이 낡은 측점 파일을 지움**(`prune_stale_cross_files` · `B05_Profile_Engine_Sections.py:144-161`) · ETag 없음 · 브라우저는 [저장]·[확정] 뒤 세션 비움(`UI_Page_Persist.ts:510`) → 다시 1.5 MB | 열쇠(측점 폴더 mtime · DB 설계 갱신 시각 · 관 · 구조물 mtime) → ETag 304 · 지우기는 쓰는 쪽(측점 만들기)으로 옮김 | 2~3 | 0.30 s · 1.5 MB → 304 · [저장] 뒤 다시 열기 빨라짐 | GET 의 지우기 부작용 — 창 둘이 같은 프로젝트 열면 서로 파일 지움 가능 | M | +| R27 | 요약(sections/{route}) 29.8 KB 중 options 만 씀 | py · `B06_Section_Router.py:228` · 화면 `design_view_cross.ts:621-667` | 작은 것 · 보류(묶기는 사 sub7) | — | 수십 ms | — | — | +| R28 | 관 지점 · 구조물 보기 바꿀 때마다 | ts · `route/structures` 파일 매번 읽기(`B05_Profile_Structures_Router.py:155-165`) · pipe-points 는 R15 계산 · 화면은 패널 · 초안 기억 따로(`Section_Drafts.ts:46,78-89`) | 한 기억 공유 · R15 저장본 | 2 | 종단 → 횡단 0.72 s 중 왕복 일부 | — | S | +| R29 | [전체 측점 반영] 4.1 s | ts · `UI_Page_Design_Sync.ts:222-239` 측점마다 전 측점 다시 셈(66×66) | 저장 아님 · **나 sub2** 몫(한 번 모아 다시 셈) | (sub2) | 4.1 s → 약 0.1 s 추정 | — | — | + +### 1-5. 이미 저장 · 잘 되는 것(손대지 않음) + +| 항목 | 자리 · 열쇠 | 근거 | +| --- | --- | --- | +| 점군 구조화 · 지면 필터 · DTM · 기본 등고선 | `processed/` · `models/` · source_identity(LAS 이름·크기·mtime) · manifest 설정 서명 | `B04_PreProcess_Engine.py:164-168` · `Engine_Pipeline.py:151-172` | +| VWorld 지도 · 도엽 zip | 메타 범위 · 도엽 번호 | `Engine.py:368` · `Engine_SheetStore.py:223-230` | +| 비용면 · 지형 뼈대 | `B05_Profile/route/cost_surface_*.npz` · 서명이 npz 안 | `B05_Profile_Engine_Solver.py:169-175,214-257` · `Engine_Skeleton.py:270-318` | +| 추천 노선 | `B05_Profile/route_recommend/.json` | R18 | +| 지표면 미리보기 glb · 등고선 · 도엽층 · 3D 길 모형 | 서버 ETag + 브라우저 IndexedDB(`aislo-asset-cache`) · 코리도는 주소에 해시 | `common_util_http_cache.py` · `b_asset_cache.ts` · `B05_Profile_UI_Corridor.ts:81-117` | +| 구조 정의 판 · 종류 | lru_cache(경로 · mtime · 크기) | `common_util_structure_catalog.py:24,81` · `B05_Profile_Structures_Schema.py:108-128` | +| 초기값 | `initial_snapshot/`(검증_sub4 28 MB · 코리도 16 MB 포함) | `common_util_initial_snapshot.py:183-221` | + +## 2. 안 — 저장 자리 · 열쇠 · 덮어쓰기 때 + +### 2-1. 한 틀 + +- 열쇠 = 입력 지문: `sha1(입력 파일 이름:mtime_ns:크기 … + 설정값 + 노선 서명 + ALGO 번호)` · 작은 입력(노선 꼭짓점 · 관 목록)은 내용 해시 — `route_signature` 그대로. +- 결과 옆 열쇠 한 쌍: 결과가 곧 산출물인 것(도엽 3D 면 · 비용면 · 배수유역)은 지금 자리 그대로 + `<이름>.key.json` 또는 npz 안 서명. +- 순수 계산 저장본(세부 유역 · 횡단 상세 조립본 · 유토 배분 · 재계산 지문)은 프로젝트 아래 한 폴더 `_derived/<종류>/<열쇠>.json` — 통째로 지워도 다시 셈으로 돌아옴 · 초기값 복사 대상에서 뺌. +- 읽기: 열쇠 같음 → 파일만 · 다름 → 셈 → 원자 쓰기(`atomic_write_json` 있음) → 같은 종류 옛 열쇠 정리(최근 2벌). +- 서버 메모리 기억(R16 · R17)은 저장 아님 — 같은 열쇠(경로 · mtime · 크기)로 요청 사이 다시 읽기만 없앰. +- 브라우저 쪽은 새 저장소 안 만듦 — 큰 파일은 ETag + IndexedDB(`b_asset_cache`) 하나 · 작은 결과는 지금 세션 칸. +- 공통 도우미 하나(`common_util` 에 열쇠 만들기 · 읽기 · 쓰기 · 정리 · 약 60줄) — 비용면 · 추천 노선 · B07 덧그림 세 곳이 따로 만든 틀을 모음(옮기기는 나중). + +### 2-2. 덮어쓰기 때 + +| 때 | 다시 만드는 것 | 지금 | +| --- | --- | --- | +| 파일 새로 올림(내용 다름) | B04 전부 · 아래 모두(열쇠가 저절로 어긋남) | 통째 지움 — 그대로 | +| 같은 파일 다시 올림 | 없음(R3) | 통째 지움 → 246 s | +| 전처리 다시(설정 바꿈) | 바뀐 갈래만 · 도엽 3D 면은 열쇠 다를 때만(R1) | 도엽 3D 면 매번 | +| 지형 바꿈(terrain switch) | 비용면 · 추천 노선 · 표본기 기억 | 비용면은 서명으로 ✓ | +| 노선 [확인] | 측점 · 종단 · 배수유역(노선 서명 다를 때만 · sub3) · 횡단 · 3D 길 모형(R19) · 초기값 | 3D 길 모형 빠짐 · 배수유역 무조건 | +| [저장] · [확정] | 서버 재계산(지문 다를 때만 R23) · 3D 길 모형(R19) · 유토 배분(R25) · 횡단 상세 열쇠 바뀜(R26) | 매번 전부 · 3D 는 브라우저 PUT | +| [초기화] | 초기값 복원(재계산 아님) — 파생 저장본은 열쇠가 알아서 | 그대로 | +| 열기 · 보기 바꿈 | 없음 — 읽기만 | 세부 유역 11번 · 유토 배분 · 상세 1.5 MB | +| 처음 한 번(자동 체인) | 지금 것 + 3D 길 모형 순서 고침 + 유토 배분 저장 | 미리 지은 3D 가 재계산 앞 | + +### 2-3. 크기(검증_sub4 기준 · 프로젝트 2.8 GB) + +- B03 입력 1.6 GB · B04 1.2 GB(structured.npz 841 MB · 마스크 49 MB ×2 · 도엽_등고선 66 + 표시본 37 MB · 지표면 미리보기 glb 8~19 MB 열 벌 남짓) · B05 18 MB · B06 2 MB · 초기값 28 MB. +- 새로 늘 것: 점군 고정 표본 필터당 6~8 MB 추정(R9) · `_derived/` 수 MB(세부 유역 0.1 MB · 상세 1.5 MB · 유토 배분 수십 KB × 2벌) · 3D 길 모형은 이미 16 MB 한 벌. +- 늘지 않게: 추천 노선 무한 쌓임 정리(R18) · 도엽 3D 면은 덮어씀 그대로. + +## 3. 데이터 3층 · 정션 · 지울 때 + +- 3층과 맞음 — 파생 저장본은 작업본에서 열쇠로 다시 셀 수 있는 값 · 정본 아님 · 사용자 조작으로 안 씀 · 지워도 값이 안 바뀜. +- 쓰는 때 = 체인 · 노선 [확인] · [저장] · [확정] · 열쇠 없을 때 첫 읽기(게으른 채움) — 자동저장(디바운스 PUT) 아님 · 사용자 값은 안 건드림. +- 잠금 오버레이 그대로 — 새로 잠그는 자리 없음(서버 짓기 1~2 s 는 [저장]·[확정] 오버레이 안). +- 계산 자리: R19 는 ② TS → 서버 Node(번들 이미 있음) · R23 · R25 는 ② 그대로 · 나머지 ③ 서버 단독 · 짝(①) 새로 안 생김. +- **지금 규칙 어김 하나** — 3D 길 모형: 브라우저가 짓고 서버는 검산 없이 받아 적음(`B05_Profile_Router_Corridor.py:131-161`) = 「브라우저에서만 계산하고 서버는 스냅샷만 보관 금지」 · R19 가 바로잡음. +- storage 정션: 랩탑 창 아홉이 메인 폴더 storage 하나를 씀 · 창마다 검증 프로젝트가 달라 겹침 없음 · 같은 프로젝트를 다른 판 코드가 열면 고정 이름 저장본(도엽 3D 면 · 배수유역 · 코리도 `corridor_{id}.json`)을 서로 덮음 → 열쇠에 ALGO 번호 · 파일 이름에 열쇠(추천 노선처럼) · 원자 쓰기. +- 지울 때: 새 파일 올림(B04 통째 · 지금 그대로) · 프로젝트 지움 · 같은 종류 옛 열쇠(최근 2벌 남김) · 노선 초기화(코리도 정리 `B05_Profile_Router_Lifecycle.py:261-276` 있음) · `_derived/` 는 언제 지워도 됨. +- 데스크탑 메인(임시 배포)은 storage 따로 — 반영은 전역 깃 싱크 뒤 처음 열 때 열쇠 없음 → 한 번 셈. + +## 4. 규칙 바꿀 거리 + +1. CLAUDE.md 5장 데이터 3층 표에 넷째 줄 「파생 저장본 — storage `_derived/` · 결과 옆 `.key.json` · 체인 · [확인] · [저장] · [확정] · 열쇠 없을 때 첫 읽기 · 지워도 다시 셈」 — 지금 「캐시」 = sessionStorage 뿐이라 서버 저장본 자리가 규칙에 없음. +2. 「GET 은 지우지 않음」 한 줄 — 횡단 상세 GET 이 측점 파일을 지움(R26). + +## 5. 다 sub3 넘김(배수유역 · 목록만) + +- primary-region 열쇠 = 형식 번호뿐(`Router_Watershed.py:239`) · [확인] 체인 무조건 `refresh=True`(`Service_Chain.py:574`) · 60 s. +- 흐름 방향 `02_flow_direction.npz` · 라우팅 `03_road_routing.npz` 저장은 있음 · 다시 쓰는 열쇠 없음. +- 도엽 등고선 좌표 바꾸기를 도엽 3D 면(`SheetSurface._load_features_metric`)과 배수유역(`Router_Watershed._reproject_features` `:114-148`)이 따로 두 번 · 저장 없음 → 한 번 바꿔 저장하면 둘 다 수 초 줄음 추정. +- 세부 유역(R15) 열쇠는 sub3 자동/수동 흐름과 같이 정함. + +## 6. 효과 큰 차례(추천) + +1. R3 같은 파일 재올림 보존 — 246 s. +2. R1 + R2 도엽 3D 면 열쇠 · 지표면 행 id 유지 — 37 s + 다시 받기 38~83 MB. +3. R10 + R9 + R12 B04 113 MB — 원인 확인 먼저(IndexedDB 열쇠 목록). +4. R19 3D 길 모형 서버 짓기 — 1.9 s 멈춤 + 15 MB 올림 · 규칙 어김 바로잡음. +5. R14 + R15 + R16 세부 유역 11번 · 표본기 기억 — 노선 편집 실시간에 직접. +6. R23 · R25 · R26 [확정] · 유토 배분 · 횡단 상세 — 1~2 s 대. +7. R18 · R11 · R4 · R5 · R7 · R24 작은 것. + +## 7. 사용자에게 물을 거리 + +1. 같은 파일을 다시 올리면 전처리 결과를 살릴지 — 추천: 살림 · 「처음부터 다시」는 확인 창에서 따로 고름. +2. 서버 「파생 저장본」(지워도 다시 세는 계산 결과)을 데이터 넷째 층으로 둘지 — 추천: 둠 · `_derived/` 한 폴더 · 종류마다 최근 2벌. +3. B04 지도에서 꺼진 층(도엽 등고선 37 MB 등)은 켤 때 받을지 — 추천: 켤 때 받음(첫 열기 37 MB 줄음). +4. 3D 길 모형을 서버가 노선 [확인] · [저장] · [확정] 때 짓고 브라우저는 받기만 할지 — 추천: 서버가 지음 · 저장 안 한 초안(벽 · 구조물)이 있을 때만 브라우저가 미리보기로 지음(올리지 않음). +5. 점군 미리보기를 고정 표본 하나로 둘지(지금은 열 때마다 무작위 50만 점) — 추천: 고정(같은 그림 · 27.8 MB 다시 받기 없음). diff --git a/docs/raw/조사/2026-10-16_341_부록5_화면배치.md b/docs/raw/조사/2026-10-16_341_부록5_화면배치.md new file mode 100644 index 000000000..64ba781ec --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록5_화면배치.md @@ -0,0 +1,176 @@ +# 341 마 · 화면 배치 (요구 231 의 1 · 3 · 4번 · sub5 · 읽기만) + +- 근거 = 파일:줄(이 판 9018ee498) · 시간 = docs/raw/조사/2026-10-16_340_계산시간_측정.md · 코드 · 서버 손대지 않음. +- 경로 줄임: `dv` = A00_Common/design · `B5` = B05_Profile/B05_Profile_UI_ · `RE` = B5 RouteEdit. + +## 결론 한 줄 + +평면(노선 편집 캔버스)을 3D 자리(종단 보기 가운데 위 칸)에 그대로 끼우고 3D 는 늦게 세우는 큰 모달로 · 노선 추천은 좌측 「노선 추천」 칸 단추 — 틀(design_page · 좌측 등록부 · 아래 종단도 한 벌)은 이미 이 꼴을 받을 자리가 있어 새 틀은 필요 없음 · 가장 큰 일은 노선 편집 모달의 「닫고 새로고침」 수명을 페이지 수명으로 바꾸는 것(L). + +--- + +## 1. 지금 B05 · B06 화면 배치 + +| 자리 | 지금(파일:줄) | 무엇이 놓임 | 비고 | +| --- | --- | --- | --- | +| 페이지 틀 | `dv/design_page.ts:104-267` `renderDesignPage` | 주소 둘(#/b05-profile · #/b06-section)이 한 페이지 · 보기 전환은 숨김 · 보임만(:235-249) | 보기는 처음 보일 때 import(:81-84) | +| 진행 단계 · 좌측 틀 | `dv/design_page.ts:153-173` `createWorkflowLayout` | 진행 단계 · 좌측 패널 · 가운데 | 좌측은 접기 가능(`revealLeft` :138) | +| 좌측 패널 칸 | `dv/design_panel.ts:240-292` 등록부 · 칸 정의 `B5Panel_Sections.ts:16-52` · `dv/design_sections.ts:20` · `B06_Section_UI_Page_Panel.ts:47-71` | 종단 보기: 구조물 배치(10) · 페이지 설정(20) · **계획노선(30) = [계획노선 편집] 단추 하나** · 선택 포인트 상세(50 · 평소 숨김) / 횡단 보기: 구조물 배치(10) · 횡단 보기 설정(20) · 표준 횡단면(30) | 칸 하나 = `registerPanelSection` 한 덩이 | +| 좌측 아래 고정 | `dv/design_dock.ts:54-131` | 구조물 목록 + [초기화] [저장] [확정] [횡단 보기/종단 보기] | 두 보기 같은 단추 | +| 가운데 위(종단 보기) | `dv/design_view_profile.ts:107` `createRouteViewer` · :597-600 | **3D 화면**(three.js) + 보기 조작 줄(`B5Panel_View.ts` · ISO/TOP · 켬끔 · [3D 업데이트]) + 불러오기 원(:589-590) | 3D 지형은 로딩에 안 넣고 뒤에서(:663-700) | +| 가운데 위(횡단 보기) | `dv/design_view_cross.ts:1-12` | 횡단 카드 목록(측점 수만큼 · 처음 보일 때 그림) | 3D 없음 | +| 가운데 아래 | `dv/design_shared.ts:150-175` `sharedProfile` · `dv/design_profile.ts` | **종단도 + 표 한 벌**(두 보기 같은 노드) · 위 겹침 = 유토곡선 · 표(`dv/design_profile_overlays.ts`) | 종단 보기 = 3D 위에 뜬 판(absolute · 60vh · `B5Style.css:41-50`) · 횡단 보기 = 흐름에 섬(`dv/design_page.css:38-41`) | +| 아래 오른쪽 | `dv/design_profile.ts:182-199` 판 자리 `side` · `B5Drainage_Side.ts:26` | **배수유역도**(2D 캔버스 평면 지도 · B04 지도 그리기 재사용 `B5Drainage_Panel.ts:1-25`) · 폭 38%(`B5Style_Drainage.css:10-24`) · 접기 | 두 보기 같은 판 | +| 새 창 떼기 | `dv/design_profile_popout.ts:1-30` | 종단 판 · 유토곡선 · 배수유역 판을 브라우저 새 창으로(DOM 만 옮김) | 3D 는 없음 | +| 노선 편집 | `RE.ts:105` `openRouteEditModal` · `RE_Chrome.ts:46-48 · :121` | 화면 통째로 덮는 모달(body 에 붙음) · 왼쪽 평면 캔버스 · 위 종단 띠 · 오른쪽 횡단 두 판 | [확인] → 서버 replan 76 s → `location.reload()`(`dv/design_view_profile.ts:278-279`) | +| 노선 추천 | `RE_Recommend.ts:159` `openModal` | 노선 편집 모달 머리 [노선 추천](`RE_Chrome.ts:55`) → 모달 위 모달 | [적용] = 편집 모달 되돌리기 한 칸 · 계산은 [확인] 때 | +| B05 ↔ B06 오감 | `dv/design_dock.ts:88` [보기 전환] · 진행 단계 칸 클릭(`dv/design_page.ts:164-167`) | 주소만 바뀜 · 보기 숨김/보임 · 0.74 s / 0.22 s(340 표) | 숨으면 3D 그리기 멈춤(`B5Page_Life.ts:26-29`) | + +## 2. 1번 — 3D 를 모달 또는 패널로 + +지금 3D 수명: +- 그리기 = `new THREE.WebGLRenderer`(`B5Viewer.ts:143`) · 매 틀 그림(바뀜 검사 없음 · :363-384) · 멈춤은 `setActive(false)`(:520-527) 하나 — 보기 전환 때만 불림(`B5Page_Life.ts:26`). **칸을 숨기거나 접기만 하면 1×1 캔버스에 계속 그림**(크기 막이 :280-285). +- 버림 = `renderer.dispose()` + `forceContextLoss()`(:545-547) · 지형 parse 는 모듈 사본 `cachedTerrain`(:44-49)에 남김(다시 parse 14.4 s 였음). +- 3D 길 모형 = [3D 업데이트]만 다시 지음(`B5Panel_View.ts:80-92` → `dv/design_view_profile.ts:304-320`) · 주 스레드 1.6~2.0 s 한 덩이(340) · 첫 짓기는 15 MB PUT(`B5Corridor.ts:206-211`) · 열 때는 지문 맞으면 저장본만(`B5Corridor.ts:273-288`). +- 3D 에 묶인 다른 몫: 측점 고름 비춤(`dv/design_view_profile.ts:141 · 147 · 229` · `dv/design_pick_profile.ts:125`) · 3D 구조물 고름(:240 · 266 · 354 · 568) · 3D 우클릭 구조물 더함(`B5Page_Structures.ts:320-326`) · **3D 노선 점 옮김 · 지움(「선택 포인트 상세」 · `B5Panel_Route.ts:83-86`) = 저장 안 되는 죽은 길**(바뀌면 측점선만 다시 그림 :364-372). + +| 항목 | 지금 | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| **안 ㄱ 큰 모달(추천)** | 3D = 종단 보기 가운데 위 상주 · 열면 지형 8 MB + parse 145 ms + 첫 틀 35~108 ms(340 부록 B) | 평면 도구줄 [3D] 단추 → `openModal({wide})`(`ui_template/ui_template_modal.ts:27` · 96vw×94vh) 몸에 `viewer.root` 를 옮겨 붙임 · **처음 열 때 만들고 닫으면 숨긴 자리로 되돌려 `setActive(false)`**(맥락 살림) · 페이지 떠날 때만 dispose · 보기 조작 줄 · [3D 업데이트] 함께 감 | `dv/design_view_profile.ts`(700줄 · 쪼갬 필요) · `B5Page_Life.ts` · 새 `dv/design_view_3d.ts`(~150) · `B5Panel_View.ts` · CSS 1 · 시험 2~3 → **6~8** | B05 첫 열기에서 3D 몫 빠짐(지형 8 MB · parse · 그리기 루프) — 첫 열기 2.1~3.0 s 중 약 0.2~0.4 s · 평면 조작 중 WebGL 루프 0 | 모달 몸에 옮긴 캔버스 크기 = ResizeObserver 가 따라감(:286-287 · 확인됨) · 열 때 지형 아직이면 로딩 원 · 측점 · 구조물 고름 비춤은 모달 열린 동안만 | M | +| 안 ㄴ 오른쪽 접는 패널 | 같음 | `ui_template/ui_template_side_panels.ts`(M02 씀 · 하나만 열림 · 폭 공유)에 「3D」 패널 · 접힘 때 `setActive(false)` 를 새로 걸어야 함 | 위 + side_panels 연결 → **7~9** | 평면과 동시에 봄 · 대신 평면 폭이 줆 · 펼친 동안 루프 계속(매 틀) | 평면 끌기(3~5 ms)와 WebGL 매 틀이 한 주 스레드 · 패널 폭 바뀔 때 두 캔버스 다시 맞춤 · **접기만으론 안 멈춤 — 걸 자리 새로** | M | +| 3D 길 모형 다시 짓기 1.9 s 언제 | [3D 업데이트] 누를 때 · 주 스레드 멈춤 | ① 모달 열 때 낡았으면 자동 1회(열기 = 사용자 의도 · 1.9 s 멈춤을 열기 원에 숨김) ② [저장]·[확정] 뒤 서버 Node 미리 짓기(`B05_Profile_Corridor_Prebuild.py` · `B05_Profile_Corridor_Node.ts` 이미 있음 · 5장 ②) → 열 때 GET 만 · ③ 열린 동안 편집이 오면 [3D 업데이트] 깜빡(`setCorridorPending` 지금 그대로) | `dv/design_view_3d.ts`(새) · `B5Corridor.ts` · 저장 흐름 1 → **2~3** | 열 때 0 s(서버 저장본) ~ 1.9 s(낡음) · 평면 · 종단 조작엔 0 | 미리 짓기 자리 · 저장본 덮어쓰기는 **라 갈래(영구저장)** · 웹 일꾼으로 옮기면 멈춤 없앰(따로 거리) | S | +| 3D 안 조작 | 보기 조작 줄 · 3D 측점 고름 · 3D 구조물 고름 · 우클릭 더함 · 노선 점 옮김(죽음) | 보기 조작 줄 · 고름 · 우클릭은 모달 안에서 그대로(같은 노드 옮김) · **노선 점 옮김 · 지움 + 「선택 포인트 상세」 칸은 지움**(평면이 유일한 노선 편집 자리) | `B5Panel_Sections.ts` · `B5Panel_Route.ts` · `dv/design_view_profile.ts`(:321-323 · 372-374) → **3** | 죽은 길 정리 · 좌측 칸 하나 줆 | 지울 것 확정 전 실행 화면에서 그 칸이 정말 쓰이지 않는지 사용자 확인 | S | + +추천 = **안 ㄱ 큰 모달**: 사용자 말(덜 중요 · 메인 차지)과 맞음 · 평면 조작 중 WebGL 0 · 틀은 공용 모달 그대로. 같이 보고 싶으면 뒤에 패널로 바꾸기 쉬움(같은 「옮겨 붙임」). + +## 3. 3번 — 노선 편집 모달 → B05 본문(평면도) + +### 3-1 모달 안 기능(전부 브라우저 · 서버는 미리보기만) + +| 기능 | 지금(파일:줄) | 서버 | 본문으로 오면 | +| --- | --- | --- | --- | +| 점 끌기 · 집기 | `RE_Pointer.ts:103` `bindRouteEditPointer` · 놓음 :312-328 | 없음(놓을 때 띠 · 경사 갱신) | 그대로 | +| 점 더함 · 지움 | `RE_Input.ts:130` dblclick · 우클릭 · `RE_Edits.ts:286` | 없음 | 그대로 · 우클릭이 배수유역도 · 종단 우클릭 메뉴(`ui_template_context_menu`)와 겹치는지 확인 | +| 곡선 셈 | `RE_Curve.ts:226` `buildEditedPolyline`(서버와 짝) | 없음 | 그대로 | +| 곡선 바 · R 라벨 | `RE_CurveBar.ts:60` · `RE_Label.ts:125` — **body 에 fixed 로 붙음**(:141) | 없음 | 본문 칸 안 절대 위치로 · 보기 숨김 때 같이 숨김 | +| 회전 | `RE_Rotate.ts:48` | 없음 | 그대로 | +| 경사 라벨 | `RE_Slope.ts:92` · 디바운스 뒤 | `POST /route/elevations` | 그대로 | +| 잠금 | `RE_Lock.ts:33-67` · 계정 설정 `routeedit-locks` | 없음 | 그대로 | +| 거리 재기 | `RE_Measure.ts:184` | `/route/elevations` | 그대로 | +| 되돌리기 | `RE_History.ts` · **window keydown Ctrl+Z/Y**(:165) · 열 때 새로 시작(`RE.ts:599`) | 없음 | **종단도도 window 에서 Ctrl+Z 를 들음**(`B5Profile_Panel_Tools.ts:323-326 · 349`) — 지금은 모달이 덮어 드러나지 않음 · 한 화면이면 두 이력이 함께 되돌려짐 → 「마지막에 만진 판」이 받게 | +| 종단 띠 | `RE_ProfileStrip.ts:46` · 편집마다 | `POST /route/profile-preview` 또는 elevations | 아래 종단도 한 벌과 겹침 → **지움 후보**(가 갈래가 종단도를 노선 편집에 바로 잇게 되면) · 그 전엔 남김 | +| 횡단 미리보기 | `RE_Cross.ts:161` · `RE_Cross_Draw.ts:111` · 오른쪽 세로 칸 `.b05-routeedit__side`(`RE.ts:177`) | `POST /route/cross-preview` | B06 카드와 겹침 → 안 A 는 오른쪽 접는 칸으로 남김 · 안 B 는 B06 카드 한 장으로 갈음 | +| 바탕 등고선 · 도엽 | `RE_Contour.ts:111` | `GET /surface/models/{id}/contour` · drainage layers | 페이지 열 때 한 번 · 배수유역도와 같은 도엽 자료 → 받기 한 벌로 | +| 초기노선 · [초기화] | `RE_Initial.ts:77 · 165` | `/route/plan` 한 번 | 4번과 함께(추천 칸) | +| 보기(팬 · 줌) | `RE_Input.ts:44` · `RE_View.ts:136 · 153` · 계정 `routeedit-view` | 없음 | `window resize`(`RE.ts:297`) → 칸 ResizeObserver 로 | +| 지형 고름 | `RE.ts:604-656` · 계정 `routeedit-terrain` | `GET /route/terrain-sources` | 「페이지 설정」 칸 또는 평면 도구줄로 | +| 그리기 | `RE_Render.ts:133` · `RE.ts:313` | 없음 | 그대로(2D 캔버스 · 바뀔 때만 그림) | + +### 3-2 모달 수명에 묶인 것 → 본문에서 바뀔 것 + +| 항목 | 지금(파일:줄) | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 자리 | `RE_Chrome.ts:46-48 · 121` body 에 덮개 · CSS 「화면 통째 덮음」(`B5Style_RouteEdit.css:1-16`) | 부모를 받는 `mountRouteEditor(parent, host)` · 덮개 클래스 걷음 · 종단 보기 가운데 위 칸(`dv/design_view_profile.ts:597-600` 3D 자리)에 붙임 | `RE_Chrome.ts` · `RE.ts` · CSS · `dv/design_view_profile.ts` → **4** | 편집 창 열기 0.54 s 사라짐(페이지 열 때 같이 받음) | 아래 종단도가 지금 **3D 위 60vh 뜬 판**(`B5Style.css:41-50`) → 평면이 가려짐 · 횡단 보기처럼 흐름에 세움(`dv/design_page.css:38-41` 규칙을 종단 보기에도) | M | +| 열 때 자료 | `RE.ts:574-579` plan · drainage layers · terrain-sources · 등고선(:639) | 페이지 열기 ③ 단계에 끼움 · `route/latest`(페이지) · `route/plan`(편집기) 두 벌 받기를 하나로 | `RE.ts` · `dv/design_view_profile.ts` · `B5Page_Latest.ts` → **3** | 받기 한 번 줆(0.09~0.13 s) | 종단 보기 불러오기 원에 평면을 넣을지(지금 3D 는 안 넣음) | S | +| [확인] | `RE_Apply.ts:77-106` replan 76 s · 덮개 · **닫고 `location.reload()`**(:67-68) | 닫지 않음 · 새로고침 대신 페이지 자료 다시 세우기(`remountRoute` 가 이미 있음 · `dv/design_view_profile.ts:660`) · 계산 자리 · 단추 뜻은 **사 갈래**(한 페이지 상태)가 정함 | `RE_Apply.ts` · `RE.ts` · `dv/design_view_profile.ts` → **3** | 다시 열기 2~3 s 를 `remountRoute` 로 · 서버 76 s 는 다 갈래(배수유역 떼면 ~6~10 s) | reload 를 쓴 까닭(PLAN 77 — 옛 관 목록 · 진행 중 요청이 살아남아 [저장]에 실림)을 다시 막아야 함 | M | +| [취소] · ✕ | `RE.ts:282-284` 닫기 = 버림 | 「연 뒤 바꾼 것 버림」 단추(이력 처음으로) · 또는 지움(페이지 [초기화]·되돌리기로) | `RE.ts` · `RE_Chrome.ts` → **2** | — | 사용자 확인(물을 거리 3) | S | +| 이력 기준 | 열 때마다 새 이력(`RE.ts:599`) · dirty = 연 뒤 바뀜 | 페이지 수명 이력 · dirty = 마지막 [저장]·[확인] 뒤 바뀜 | `RE_History.ts` · `RE.ts` → **2** | — | 보기 전환(B06 갔다 옴)에도 이력 남김 | S | +| 편집 값 보관 | **메모리만**(`RE.ts:116-173` 지역 변수) — 새로고침하면 사라짐 | 5장 「캐시 = 사용자 조작 즉시」대로 sessionStorage 초안(`b_page_state`)에 · 페이지 [저장]이 들고 감 | `RE.ts` · `RE_Edits.ts` · `b_page_state` → **3** | — | 지금 모달은 5장 캐시 층을 안 따름(규칙 바꿀 거리 아님 · 맞추는 일) · 저장 묶음은 사 갈래 | M | +| 키 · 창 듣기 | window keydown(`RE_History.ts:165`) · resize(`RE.ts:297`) · 닫을 때 뗌(`RE.ts:251-258`) | `host.onHide` 뗌 · `onShow` 붙임 · `onDispose` 정리(`dv/design_page.ts:57-69` 이미 있음) · Ctrl+Z 는 「활성 판」 하나만 | `RE_History.ts` · `B5Profile_Panel_Tools.ts` · `RE.ts` → **3** | — | 종단도 ▲▼ 방향키도 window(`B5Profile_Panel_Tools.ts:309-349`) — 평면은 방향키를 안 써 겹침 없음(확인) | S | +| 덮개(busy) | 상자 전체 · 약 90 s 타이머(`RE_Chrome.ts:118`) | 5장 잠금 오버레이 자리 = 「노선 재탐색」 → 그대로 허용 · 다만 본문이면 페이지 전체 잠금 | — | — | 배수유역을 떼면(다 갈래) 6~10 s · 그보다 길면 「조용히 뒤에서」로 | S | +| 시험 | 노선 편집 시험 9벌이 모달 꼴을 봄(`resources/tester/test_b05_routeedit_*.py` · `test_b05_routeedit_chrome_modal.py`) | 꼴 시험 고쳐 씀(지우지 않음 · 새로 둠) | 시험 **4~9** | — | — | M | + +### 3-3 지울 것 + +| 지울 것 | 자리 | 비고 | +| --- | --- | --- | +| 좌측 「계획노선」 칸 + [계획노선 편집] 단추 | `B5Panel_Sections.ts:28-38` · `B5Panel_Route.ts:74-76` · 콜백 `dv/design_view_profile.ts:278-285` | 사용자 지시(231-3) | +| 좌측 「선택 포인트 상세 설정」 칸 + 3D 점 옮김 · 지움 | `B5Panel_Sections.ts:40-52` · `B5Panel_Route.ts:78-105` · `dv/design_view_profile.ts:321-323 · 373` | 저장 안 되는 죽은 길(1번 3D 이사와 같이) · 사용자 확인 | +| 모달 덮개 · 전체 화면 CSS | `RE_Chrome.ts:46-121` · `B5Style_RouteEdit.css:1-16` | 겉틀만 · 안 칸은 살림 | +| `location.reload()` 콜백 | `dv/design_view_profile.ts:279` | `remountRoute` 로 | + +크기 합: **L**(파일 약 10~12 + 시험 4~9). + +## 4. 4번 — 노선 추천을 좌측 따로 칸 단추로 + +| 항목 | 지금(파일:줄) | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 단추 자리 | 편집 모달 머리 [노선 추천](`RE_Chrome.ts:55`) · 「현재 추천: ○○」(`:53`) · [초기화](`:78`) — `createInitialPanel` 이 덮개 안에서 집음(`RE_Initial.ts:79-81`) | 좌측 새 칸 「노선 추천」(`registerPanelSection` · 차례 25 = 구조물 배치 · 페이지 설정 사이 또는 30 = 지운 계획노선 자리) · 몸 = [노선 추천] 단추 + 현재 추천 한 줄 + [초기화] | `B5Panel_Sections.ts` · 새 `B5Panel_Recommend.ts`(~60) · `RE_Initial.ts`(요소 집기를 밖에서 받게) · `RE_Chrome.ts`(단추 지움) → **4** | — | 칸 차례 사용자 확정(물을 거리 4) | S | +| 추천 창 | 모달 위 모달(`RE_Recommend.ts:159` `openModal` · z-index +2 `B5Style_RouteRecommend.css:14`) · 편집 모달 상태 안 읽음 · 받는 값은 `RecommendParams`(:113-136) 하나 | 창은 그대로 공용 모달(평면이 본문이라 이제 모달 하나) · 열 때 `current` = 본문 편집기 지금 점 | `RE_Recommend.ts`(모달 위 모달 키 막기 :561-566 정리) → **1** | — | 창 안에도 지도 캔버스 하나(`RE_Recommend_Map.ts`) — 본문 평면과 겹침 · 그대로 둠(미리보기 전용) | S | +| [적용] | 미리보기 → 편집 모달 `restoreSnapshot(…, record)` 되돌리기 한 칸(`RE.ts:264 · 455-461`) · 계산은 [확인] 때(`RE_Apply.ts:98`) | 본문 편집기가 늘 있으므로 **같은 함수 그대로** — 본문 평면에 적용 · 되돌리기 한 칸 · 서버 계산은 사 갈래 뜻의 [확인]/[저장] 때 | `RE_Initial.ts` · `RE.ts` → **2**(3번과 같이) | 0 s(브라우저) | 3번 없이 4번만 하면 「편집기 없음」 → 편집 모달을 미리 채워 열거나 바로 replan(되돌리기 빠짐) — **3번 다음에 하는 것이 작음** | S | +| 미리 셈 | 자동설계 체인 뒤 다섯 갈래 미리 셈(`B03_FileInput_Service_Chain.py:353-363` · `B05_Profile_Router_RouteInitial.py:176-190`) · 저장 = `B05_Profile/route_recommend/<지문>.json`(`B05_Profile_Engine_RouteInitial_Store.py:35 · 86-121`) · 기본 입력이면 저장본 1.3 s | 그대로 — 화면 자리만 바뀜 | **0** | — | 노선이 바뀐 뒤 다시 미리 셈 여부 = 라 갈래 | — | +| 시험 | `test_b05_routeedit_initial.py:171-283` · `test_modal_top_and_add_word.py:37` 가 머리 단추 · CSS 를 봄 | 고쳐 씀 | 시험 **2** | — | — | S | + +크기 합: **M**(3번 뒤 · 파일 약 5 + 시험 2). + +## 5. 한 화면에 놓기 — 안 둘 + +공통: 좌측 패널 · 아래 단추 넷 · 종단도 한 벌 · 배수유역 판 · 구조물 폼 · 꾸밈(테마 토큰 · ui-sidebar-section · 접기 손잡이 · 새 창 떼기)은 그대로. 바뀌는 것은 가운데 위 칸 하나와 종단도 판의 「뜸 → 흐름」뿐. + +### 안 A — 3D 자리에 평면 · 보기 둘 유지(추천) + +``` +┌좌측 패널────────┬─ 가운데 위: 평면(노선 편집 캔버스) ─────────────┬ 횡단 미리보기(접기) ┐ +│ 구조물 배치 │ [도구줄: 곡선 · 회전 · 잠금 · 재기 · ↶↷ · 3D] │ 선택 측점 횡단 두 판 │ +│ 노선 추천 [추천] │ │ │ +│ 페이지 설정 │ │ │ +│ ├══ 끌어 높이 ═══════════════════════════════════════════════════════════┤ +│ │ 종단도 + 표 (위 겹침: 유토곡선) │ 배수유역도(흐림 · [업데이트]) │ +│ [초기화][저장] │ │ │ +│ [확정][횡단 보기]│ │ │ +└──────────────────┴──────────────────────────────────────────┴──────────────────────────────────┘ +횡단 보기 = 가운데 위만 횡단 카드 목록(지금 그대로) · 3D = [3D] → 큰 모달 +``` + +| 항목 | 지금 | 바꾸면 | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 가운데 위(종단 보기) | 3D | 평면 편집기 | 2 · 3번 표 | 노선 고침 · 종단 · 배수유역이 한 화면 · 편집 창 열기 0.54 s 없음 | 횡단 카드는 여전히 보기 전환(0.74 s) | L | +| 종단도 판 | 3D 위 뜬 판 60vh | 흐름에 섬(횡단 보기와 같은 규칙) · 끌어 높이 그대로 | `dv/design_page.css` · `B5Style.css` → **2** | 평면이 가려지지 않음 | 끌기 높이 저장 키 그대로 쓰는지 | S | +| 횡단 미리보기 | 편집 모달 오른쪽 칸 | 평면 오른쪽 접는 칸(지금 `RE_Cross` 그대로) | 3번에 포함 | 측점 클릭 → 0.07 s 대 미리보기 | B06 카드와 값 다름 가능(미리보기 = 서버 cross-preview · 카드 = 브라우저 설계) — 나 갈래 | S | +| 파일 · 크기 | — | 새 파일 2~3(`design_view_3d` · `B5Panel_Recommend` · 편집기 마운트) · 고침 12~15 · 시험 6~10 | — | — | `dv/design_view_profile.ts` 700줄 꽉 참 → 먼저 쪼갬(바 갈래) | **L** | + +### 안 B — 평면 · 횡단 카드 나란히 · 보기 하나 + +``` +┌좌측 패널────────┬─ 가운데 위 왼쪽: 평면 ───────────────────┬─ 오른쪽 접는 패널 셋(하나만 열림) ─┐ +│ 구조물 배치 │ │ [횡단] 선택 측점 B06 카드 한 장 │ +│ 노선 추천 │ │ [배수유역] 배수유역도 │ +│ 페이지 설정 │ │ [3D] 3D(열린 동안만 그림) │ +│ 횡단 보기 설정 ├══ 끌어 높이 ═══════════════════════════════╧═════════════════════════════════════┤ +│ 표준 횡단면 │ 종단도 + 표 (위 겹침: 유토곡선) — 폭 전체 │ +│ [초기화][저장]… │ │ +└──────────────────┴────────────────────────────────────────────────────────────────────────────────┘ +전체 측점 카드 목록 = [횡단 목록] 단추(모달 또는 지금 횡단 보기) +``` + +| 항목 | 지금 | 바꾸면 | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 오른쪽 패널 | 없음 | `ui_template/ui_template_side_panels.ts`(M02 씀)로 횡단 · 배수유역 · 3D 셋 | `ui_template_side_panels` 연결 · `dv/design_profile.ts`(배수유역 판을 side 에서 뗌 :182-199) · `B5Drainage_Side.ts` · 새 패널 묶음 → **5~7** | 평면 · 종단 · 횡단 한 장이 전환 없이 한 화면 | 배수유역 판이 아래 판 자리 약속(`side`)에서 빠짐 · 새 창 떼기(`dv/design_profile_popout.ts`) 다시 맞춤 · 3D 패널 접힘 때 `setActive(false)` 새로 | L | +| 횡단 카드 한 장 | 횡단 보기 = 카드 목록 전체 | 선택 측점 카드 하나를 오른쪽 패널에 · 목록 전체는 따로 | `dv/design_view_cross.ts`(683줄) · B06 카드 그리기 → **3~5** | 측점 고름 → 카드 0.04 s | 횡단 조정창 · 구조물 폼(B06 몫)이 카드 목록 수명에 묶임 — 나 · 사 갈래 | L | +| 좌측 칸 | 보기마다 다름 | 보기 하나 → 칸 합침 | `dv/design_panel.ts` · 칸 정의 2 → **3** | — | 좌측이 길어짐 | M | +| 파일 · 크기 | — | 새 4~6 · 고침 20+ · 시험 10+ | — | — | 꾸밈 유지하나 화면 틀이 바뀜 · 사용자 「화면 비치 · 요소 유지」(231-8)와 부딪힘 | **L+** | + +추천 = **안 A**: 지금 틀 · 칸 · 판을 거의 그대로 쓰고(231-8 「배치 · 요소 유지」), 3번 · 1번 · 4번이 차례로 쌓임(3 → 1 → 4). 안 B 는 안 A 뒤 「횡단 미리보기 칸」을 B06 카드 한 장으로 바꾸는 한 걸음으로 갈 수 있음. + +## 6. 해 나갈 차례(추천) + +1. `dv/design_view_profile.ts` 쪼갬(700줄 · 바 갈래와 맞춤) — S +2. 3D → 큰 모달(1번 안 ㄱ) + 죽은 3D 노선 점 길 지움 — M +3. 노선 편집 → 가운데 위 본문(3번) · 종단도 판 흐름으로 · 편집 초안 sessionStorage — L +4. 노선 추천 → 좌측 칸(4번) — S~M +5. (뒤) 종단 띠 지움 · 횡단 미리보기 ↔ B06 카드 맞춤 — 가 · 나 갈래 결과 뒤 + +## 7. 규칙 바꿀 거리(5장) + +- 초기값 쓰는 때 = 「노선 [확인] 직후」(5장 표). 노선 [확인]이 본문에서 페이지 [저장]·[확정]에 녹으면 이 줄을 고쳐야 함 — 사 갈래와 같이 정함. +- 잠금 오버레이 자리 = 「노선 재탐색」. 본문 평면에서 76 s(지금) 잠금은 페이지 전체를 막음 — 배수유역을 뗀 뒤(다 갈래) 6~10 s 면 그대로 · 그 밖이면 「조용히 뒤에서」로 자리에서 빼는 것을 검토. + +## 8. 사용자에게 물을 거리 + +1. 3D 는 큰 모달(추천) 또는 오른쪽 접는 패널? — 추천 모달(평면 조작 중 3D 안 그림 · 덜 중요한 정보). +2. 화면 배치 안 A(3D 자리에 평면 · 횡단 보기 전환 유지 · 추천) 또는 안 B(평면 + 오른쪽 패널 횡단 · 배수유역 · 3D · 보기 하나)? — 추천 안 A. +3. 본문 평면의 [확인] · [취소] 단추를 남길지(노선만 서버로 다시 셈) 또는 페이지 [저장]·[확정] 하나로 합칠지? — 추천: [확인] 남김(이름 「노선 반영」) · [취소] = 「반영 전으로 되돌림」 · 합침은 사 갈래 결과 뒤. +4. 좌측 「노선 추천」 칸 자리 — 지운 「계획노선」 자리(페이지 설정 아래 · 추천) 또는 맨 위? +5. 3D 노선 점 옮김 · 지움과 「선택 포인트 상세 설정」 칸(저장 안 되는 길)을 지워도 되는지? — 추천 지움. +6. 노선 편집 위 「종단 띠」 — 아래 종단도가 실시간으로 따라오게 되면 지울지? — 추천 그때 지움(그 전엔 남김). +7. 3D 길 모형 다시 짓기 — 모달 열 때 낡았으면 자동(1.9 s) 또는 [3D 업데이트] 누를 때만(지금)? — 추천 열 때 자동 + 서버 미리 짓기(라 갈래). diff --git a/docs/raw/조사/2026-10-16_341_부록6_하위폴더.md b/docs/raw/조사/2026-10-16_341_부록6_하위폴더.md new file mode 100644 index 000000000..4c7cc24fc --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록6_하위폴더.md @@ -0,0 +1,164 @@ +# 341 바 · 하위 폴더 (요구 231-8) — sub6 · 읽기만 + +- 범위: B04 · B05 · B06 (+ B07 · A00_Common/design · common_util 겹침) · 코드 고침 없음 · 서버 안 띄움. +- 잰 날: 2026-10-16 · 기준 = sub_laptop_6 받은 뒤 HEAD · 셈은 git ls-files · 정규식 import 풀이(대략값 ±5%). + +## 결론 한 줄 + +**조건부** — 지금 파일 대이동은 안 함 · 페이지 폴더 CLAUDE.md 는 바로(S) · `logic/` 하위 폴더(DOM 없는 계산만)는 341 실시간 코드 작업과 함께 갈래별로 · 파이썬은 옮기지 않음. + +## 1. 파일 전수 + +| 폴더 | ts | py | css | 줄(합) | 비고 | +| --- | --- | --- | --- | --- | --- | +| B04_PreProcess | 18 · 7,078 | 41 · 11,818 | 2 · 850 | 19,746 | 무게 = 파이썬(배수유역 엔진 7 · 2,898줄 · 라우터 9 · 2,754줄) | +| B05_Profile | 149 · 34,883 | 35 · 12,766 | 7 · 3,260 | 50,909 | + Old/ 27 · 9,730줄(아무도 안 부름 · tsconfig.json:38 제외) | +| B06_Section | 94 · 25,882 | 20 · 6,985 | 5 · 2,312 | 35,179 | UI_Cross 한 갈래가 59 · 15,903줄 | +| A00_Common/design | 35 · 6,000쯤 | — | 2 | 6,676 | B05 · B06 한 페이지 뼈대(router.ts:55-56 · 둘 다 design_page) — **이미 하위 폴더** | +| common_util | 52쯤 | 27쯤 | — | 17,489 | 이미 공용(횡단 설계 · 유토 · 노선 기하 · 구조물 측점 · ① 짝 여럿) | +| B07(맨 위 · CAD 앱 뺌) | 11 · 2,946 | 32 · 11,623 | 1 · 461 | 15,030 | | + +이름 갈래(앞머리) — 앞머리가 이미 폴더 노릇: + +| 폴더 | 갈래(파일 · 줄) | +| --- | --- | +| B05 ts | UI_RouteEdit 27 · 7,419 · UI_Corridor 28 · 7,174 · UI_Profile 25 · 5,716 · UI_Structures 20 · 4,474 · UI_Drainage 18 · 4,241 · UI_Viewer 7 · 1,438 · Api 6 · 1,219 · UI_Page 6 · UI_Panel 6 · 그 밖 6 | +| B05 py | Engine_Grade 4 · Engine_RouteInitial 7 · Engine_Sections 2 · Engine_RidgeValley 2 · Router 7 · Structures 4 · 그 밖 9 | +| B06 ts | UI_Cross 59 · 15,903 · UI_Page 15 · 4,011 · UI_Section 6 · Api 3 · 그 밖 11 | +| B06 py | Engine_* 9 · Router 7 · Repository 2 · Schema · Server_Calc_Prebuild | +| B04 ts | UI_Map*(Render · Overlays · Layers · Viewer) 5 · UI_Terrain 3 · UI_Flow* 3 · Basins · Watershed · Page · Api | +| B04 py | Engine_* 26 · Router 9 · Repository · Schema · Service | + +입구 · 경로: + +| 항목 | 자리 | 하위 폴더에 닿나 | +| --- | --- | --- | +| vite | 뿌리 = A00_Common(vite.config.ts:20) · 별칭 @ui · @util · @config 뿐(:24-34) · 페이지는 router.ts:52-58 동적 import | 페이지 안 이동은 vite 설정 안 바뀜 · 상대 import 만 바뀜 | +| 서버 Node 묶음 입구 | package.json:9 build:corridor = B05_Profile_Corridor_Node.ts · :10 build:server-calc = B06_Section_Server_Calc_Node.ts | 입구 파일을 옮기면 두 줄 + 시험 2(test_b06_ground_unlock.py:17 · test_b06_height_unlock.py:17) | +| 묶음 낡음 판정 | common_util_node_bundle.py:23 SOURCE_DIRS(B05 · B06 · B08 · common_util · rglob) · :28 SOURCE_GLOBS | rglob 이라 하위 폴더 그대로 잡힘 | +| 파이썬 | __init__ 없는 이름공간 패키지 · main.py:42-63 라우터 22줄 · 절대 import(B05 334줄 · 141파일 / B06 208 · 110 / B04 136 · 57) | 옮기면 모듈 경로 전부 바뀜 | +| 파이썬 자기 위치 | B05_Profile_Corridor_Prebuild.py:31 · B06_Section_Server_Calc_Prebuild.py:57 `parents[1]` · B04_PreProcess_Engine_GisVector.py:20-23 · B05_Profile_Structures_Schema.py:28 | 한 단 깊어지면 뿌리 경로 틀림(조용히) | +| 시험 | resources/tester · B05 189 · B06 185 · B04 58 파일이 이름을 씀 · TS 파일 경로 글자로 읽는 시험 86 파일(문자열 B05 119 · B06 100 · B04 40) · mock 문자열 1(test_b05_extra_stations_supplier.py:289) | 옮기면 문자열 경로 깨짐(빨강으로 드러남) | + +서로 부르는 관계(import 줄 · 같은 폴더 안 / 밖): + +| 부르는 쪽 → 받는 쪽 | ts | py | +| --- | --- | --- | +| B05 안 | 503 | 91 | +| B06 안 | 416 | 48 | +| B04 안 | 43 | 78 | +| B05 → B06 | 59 | 11 | +| B06 → B05 | 31 | 26 | +| B05 → B04 | 56 | 3 | +| A00_Common(+design) → B05 / B06 | 76 / 40 | — | +| B07 → B05 / B06 | 4 / 13 | 10 / 5 | +| B08 · B09 · M02 → B05 · B06 | 10 | 15 | + +## 2. 공용 로직이 정말 없나 — **있음 · 다만 페이지 폴더에 페이지 이름으로 삶** + +이미 공용 자리: + +| 자리 | 무엇 | +| --- | --- | +| common_util(17,489줄) | 횡단 설계 · 면적(cross_design*) · 유토곡선(mass_haul* 8) · 사토(spoil_fill ① 짝) · 소단(cross_berm ① 짝) · 구조물 측점(structure_station ① 짝) · 노선 기하(route_geometry · route_polyline py) · 측점 표기(common_util_station.ts:10 stationLabel) | +| A00_Common/design(6,676줄) | B05 · B06 한 페이지 뼈대 · 가게(design_store) · 저장(design_save) · 초기화(design_reset) · 구조물 명세(design_structure_*) | +| ui_template | 화면 요소 · 문구 | + +다른 페이지가 부르는 페이지 파일(A00/design · 시험 뺌) — 이름은 페이지인데 실제는 공용: + +| 주인 | 파일 수 | 누가 부르나 | 예 | +| --- | --- | --- | --- | +| B06 ts | 약 22 | B05 · B07 | UI_Cross_Culvert · Box · Ford · Ford_Pavement · Revetment · Wall_Hatch · Culvert_Solve · Culvert_Wire · Section_Common · Section_Store · Api_Fetch | +| B05 ts | 약 17 | B06 · B07 · B08 · M02 | Api_Structures · Api_Pipes_Draft · UI_Profile_Alignment · Profile_Edit · Structures_Balloon · Structures_Snap · Drainage_Ford_Fill | +| B04 ts | 7 | B05 | UI_MapRender · MapRender_Prepare · MapOverlays · FlowRamp · FlowArrows · Camera · RouteSamples | +| B05 py | 9 | B06 · B07 · M02 | Engine_Grade* · Engine_Sections* · Structures_Schema(52줄이 부름) · Structures_Repository | +| B06 py | 5 | B04 · B05 · B07 · B08 | Engine_Culvert · Engine_Design · Repository | + +겹친 로직(같은 일 여러 벌): + +| 일 | 벌 수 | 자리 | +| --- | --- | --- | +| 1차 선형 보간(오프셋 → 지반고 · 측점 → 값) | 7+ | B05_Profile_UI_Profile_Alignment.ts:155 · B05_Profile_UI_RouteEdit_Frame.ts:44 · B05_Profile_UI_Profile_Table.ts:421 · B06_Section_UI_Cross_Culvert_Solve.ts:30 · common_util_cross_design.ts:260 · common_util_cross_berm.py:234 · B07_DesignDetail_Engine_Cad.py:257 · B07_DesignDetail_Engine_Cad_PlanSlope.py:59 | +| 측점 → 평면 점(노선 따라 보간) | 4+ | B04_PreProcess_UI_RouteSamples.ts:38(1 m 표본 반올림) · B05_Profile_UI_RouteEdit_Frame.ts:44 · B05_Profile_UI_Corridor_Loft_Profile.ts:120 · B05_Profile_Engine_Sections_Core.py:98 · common_util_route_geometry.py:593 | +| 측점 간격 추정(최빈 간격) | 2(py · 기본값 다를 수 있음) | B05_Profile_Engine_Grade_Profile.py:61 · B07_DesignDetail_Engine_Cad.py:288 | +| 측점 표기(py) | 1 + TS 1 | B05_Profile_Engine_Sections_Core.py:60 format_station ↔ common_util_station.ts:10 — 짝 표기 없음 | +| 면적 표기(ha · ㎡) | 3 | B04_PreProcess_UI_Basins.ts:82 · B04_PreProcess_UI_FlowStrength.ts:78 · B05_Profile_UI_Drainage_Parts.ts:87 | +| 같은 이름 함수(폴더 둘 넘게) | 53 | 대부분 이름만 같고 일은 다름 · 위 표가 진짜 겹침 | + +→ 겹침은 작은 도우미 수준(각 10~20줄) · 큰 계산은 이미 common_util 한 벌. 「공용이 없다」보다 「공용인데 자리 · 이름이 페이지」가 맞는 진단. + +화면 · 계산 섞임(341 실시간과 직결): + +| 셈 | B05 ts | B06 ts | B04 ts | A00/design | +| --- | --- | --- | --- | --- | +| DOM 씀(document · HTMLElement · sessionStorage 등) | 80 · 22,124줄 | 54 · 15,629 | 12 · 5,633 | 18 · 4,336 | +| 서버 요청(fetch) | 31 · 5,931 | 33 · 9,118 | 2 · 890 | 3 · 393 | +| three.js 만 | 6 · 1,460 | 0 | 0 | 0 | +| 순수 계산(위 셋 없음) | 17 · 3,669 | 4 · 534 | 4 · 573 | 12 · 1,743 | +| 순수지만 DOM 파일을 부름 | 15 · 1,848 | 3 · 695 | 0 | 2 · 239 | + +- 서버 Node 묶음(② TS → 서버 Node)이 끌어가는 파일: corridor 63 · server-calc 52(타입 import 뺌) — 그 안에 DOM 파일 · ui_template 13(알림 · 문구 locale 아홉) · A00_Common/b_page_state(sessionStorage) 포함. 지금은 DOM 이 함수 안에만 있어 돎 · 모듈 맨 위에 DOM 한 줄이 들어가면 서버 계산이 깨짐. +- 곁 흠(확인 거리 · 고치지 않음): 묶음 낡음 판정(common_util_node_bundle.py:23 · :28)이 ui_template · A00_Common/b_page_state · config 를 안 봄 — 거기만 바뀌면 묶음 다시 안 지음. + +## 3. 하위 폴더 안 — 안 여섯 + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| A 갈래별 대이동 | B05 ts 149 · B06 94 · B04 18 가 한 폴더 · 앞머리로 갈래(B05_Profile_UI_RouteEdit_*) · 실행 시간과 무관 | `B05_Profile/route_edit/` · `corridor/` · `profile/` · `structures/` · `drainage/` · `viewer/` · `page/` · `api/` · B06 `cross/` · `section/` · `page/` · B04 `map/` · `terrain/` 로 git mv · 화면 · 요소 그대로 | 옮김 261 · import 줄 810 · 고칠 파일 293 · 시험 문자열 경로 164 | 실행 0 · AI = ls 소음 줄음(B05 211칸 → 갈래당 6~29) · 찾기 횟수는 그대로(앞머리 glob 과 같음) | 하루 약 14커밋(9-16~10-16 427) · 여덟 창 병행 중 이동 = 옛 경로 새 import 가 합친 뒤 typecheck 빨강 · 시험 86 파일 문자열 경로 · git log --follow 필요 | L | +| B `logic/` 하위 폴더(DOM 없는 계산만) | 순수 계산 43파일 · 6,000줄쯤이 화면 파일 사이에 섞임 · 서버 묶음이 DOM 파일까지 끌어감(위 표) | 페이지마다 `logic/` · 규칙 「DOM · three · fetch · sessionStorage 금지」 · ① 짝 TS 쪽 · ② 서버 Node 묶음이 부르는 계산은 여기만 · 섞인 파일은 손댈 때 계산 부분만 떼어 옮김 | 1차(이미 순수 43) = import 줄 192 · 파일 113 · 시험 문자열 18 · 2차는 갈래별 섞인 파일 쪼갬 | 실행 0 · 341 실시간 새 계산(평면 → 종단 · 종단 → 횡단)이 「브라우저 즉시 + 서버 정본 재계산」 같은 코드를 쓰는 자리가 경로로 보임 · AI 가 「서버 묶음에 들어가나」를 경로로 판정 | 섞인 파일 쪼개기는 코드 고침(이동만이 아님) · 묶음 입구 package.json:9-10 · 낡음 판정 rglob 확인 · 쪼갠 뒤 묶음 결과 대조 시험 | M | +| C 폴더별 CLAUDE.md(옮기지 않음) | 뿌리 CLAUDE.md 하나 + docs 넷 · 페이지 폴더에 없음 | `B05_Profile/CLAUDE.md` · `B06_Section/CLAUDE.md` · `B04_PreProcess/CLAUDE.md` · `A00_Common/design/CLAUDE.md` — 그 폴더 파일을 읽을 때 붙음 · 내용 = 갈래 지도 · 짝 파일 · 묶음 입구 · 공용 자리 · 금지 | 새 파일 4 · 코드 0 | 실행 0 · AI = 갈래 · 짝 · 서버 묶음 · 남이 부르는 파일을 처음부터 앎 · 옮기기 없이 효과 대부분 | 짧은 지시형 유지(길면 매번 문맥 먹음) · 코덱스는 AGENTS.md 쪽(지침 따로) | S | +| D 페이지 넘는 공용을 공용 자리로 | B06 UI_Cross 구조물 그림 22 · B04 지도 그리기 7 · B05 구조물 · 종단 17 · 1차 보간 7벌 · 측점 간격 2벌 | 손댈 때 common_util(계산) 또는 A00_Common/design(B05 · B06 화면 공용)으로 · 보간 · 간격은 한 벌로 | 갈래당 5~25 | 실행 0 · 「이름이 주인을 속임」 없앰 · 고칠 때 한 곳 | 한 번에 하면 A 와 같은 충돌 · 손댈 때만 | M | +| E 파이썬 옮기기 | 절대 import 678줄 · 308파일 · main.py 22줄 · parents[1] 넷 | 안 함 | — | — | 옮기면 뿌리 경로 조용히 틀림(Prebuild 둘 · GisVector · Structures_Schema) · 요구 8번은 프론트 | — | +| F Old/ | B05_Profile/Old 27 · 9,730줄 · 부르는 곳 0 · tsconfig 제외 · 마지막 87ffe800e(10-09) | 지울지 · 둘지 사용자 몫 | 0~1 | AI = glob · grep 잡음 9,730줄 빠짐 | docs 셋이 경로를 적어 둠(기록이라 그대로) | S | + +## 4. AI 코드 작성에 도움 되나 — 근거 + +최근 커밋 50(10-12 ~ 10-15 · B05 · B06 · A00/design 손댄 것 · 합치기 뺌): + +| 셈 | 값 | +| --- | --- | +| 커밋당 파일(시험 포함) | 중앙 7 · 평균 12.2 · 최대 70 | +| 커밋당 코드 파일(B05 · B06 · design) | 중앙 3 · 평균 5.3 · 최대 22 | +| 커밋당 윗 폴더(시험 포함) | 중앙 3 · 평균 3.7 · 최대 13 | +| 커밋당 이름 갈래 | 중앙 2 · 평균 3.7 · 최대 14(322-1 · 323-5 구조물표) | +| B05 · B06 둘 다 손댄 커밋 | 23 / 50 | +| 시험도 손댄 커밋 | 44 / 50 | +| 함께 손댄 다른 폴더 | M02 35 · common_util 33 · A00_Common 31 · ui_template 21 · B04 8 · B07 7 | + +찾기 표본(341 갈래가 찾을 것): + +| 찾을 것 | grep | 닿은 파일 | +| --- | --- | --- | +| 관경 자동지정 | 1번 | B05_Profile_UI_Drainage_Panel_Types.ts · UI_Profile_Panel_Types.ts · common_util_drainage_detail.py | +| 노선 편집 창 열기 | 1번 | UI_RouteEdit 다섯 + design_view_profile.ts | +| 3D 가운데 자리 | 1번 | design_page.ts(mountCenter) | + +판정: +- 찾기 횟수 — 폴더와 무관. 앞머리 이름 + 한글 머리 주석이 이미 grep 한 번에 닿게 함 · 하위 폴더는 glob 하나를 다른 glob 으로 바꿀 뿐. +- 흩어짐 — 기능(구조물 · 측점) 축으로 B05 · B06 · design · common_util · M02 를 가로지름 · 페이지 안 갈래 폴더(A)는 이 흩어짐을 못 줄임. +- 진짜 비용 — 「이 파일이 화면 전용인가 · 서버 묶음에도 들어가나 · 남의 페이지가 부르나」를 알려면 import 를 따라가야 함 · B(logic/) + C(CLAUDE.md)가 이것을 경로 · 지침으로 드러냄. +- 손해 — A 는 고칠 파일 293 · 하루 14커밋 · 여덟 창 병행 · 시험 문자열 164 · git 이력 끊김(--follow) · 묶음 입구 두 줄 · B 1차는 그 약 1/3. + +## 5. 결론 · 차례 + +| 차례 | 할 일 | 언제 | 크기 | +| --- | --- | --- | --- | +| 1 | C 폴더별 CLAUDE.md 넷(갈래 지도 · 짝 · 묶음 입구 · 남이 부르는 파일 · logic 규칙) | 바로 · 코드 무관 · 충돌 없음 | S | +| 2 | 규칙 정함(아래 「규칙 바꿀 거리」) | 341 새 계획서와 함께 | S | +| 3 | B 1차 — 이미 순수한 43파일 `logic/` 로 git mv(내용 고침 없이 import 만) · 한 창 한 커밋 · 묶음 다시 지어 결과 대조 · typecheck · 고친 대상 시험 | 전역 깃 싱크 직후 · 다른 창 쉴 때 · 끝나면 곧바로 싱크 | M | +| 4 | B 2차 · D — 341 실시간 갈래(가 평면 → 종단 · 나 종단 → 횡단 → 유토곡선)를 짤 때 새 계산은 처음부터 `logic/` · 손대는 섞인 파일만 계산을 떼어 옮김 · 보간 · 측점 간격 한 벌 | 갈래별 · 그 갈래 작업 안에서 | M | +| — | A 대이동 · E 파이썬 이동 | 안 함 | — | + +규칙 바꿀 거리(CLAUDE.md 4 · 5장): +- 4장 코딩 규칙에 「`logic/` = DOM · three · fetch · sessionStorage 금지 · 화면 파일은 logic 을 부르고 logic 은 화면을 안 부름」. +- 5장 ② 「TS 를 서버 Node 로」에 「묶음이 부르는 계산은 `logic/` 과 common_util 만」. +- 4장 「새 계산 파일은 갈래 하위 폴더에」 — 앞머리 이름은 그대로(B05_Profile_*) 두어 grep · 시험 이름 유지. + +## 사용자에게 물을 거리 + +1. 지금 파일 대이동(A)은 안 하고 폴더별 CLAUDE.md(C)부터 — 추천: 예. +2. `logic/`(DOM 없는 계산만) 하위 폴더를 341 실시간 작업의 계산 자리로 정할지 — 추천: 예 · 이름은 `logic`. +3. 하위 폴더 안 파일 이름 — 앞머리(B05_Profile_*) 그대로 둘지 · design 처럼 짧게 바꿀지 — 추천: 그대로(시험 · grep · 이력 유지). +4. B05_Profile/Old 27파일(9,730줄 · 부르는 곳 0) — 추천: 지움(git 이력에 남음). +5. 파이썬은 옮기지 않음 — 추천: 예. +6. B 1차 이동 시점 — 추천: 다음 전역 깃 싱크 직후 · 다른 창 쉴 때 한 창이. diff --git a/docs/raw/조사/2026-10-16_341_부록7_한페이지.md b/docs/raw/조사/2026-10-16_341_부록7_한페이지.md new file mode 100644 index 000000000..cc7a0b52c --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록7_한페이지.md @@ -0,0 +1,92 @@ +# 341 사 — 한 페이지 상태 (요구 231-5 · B05 · B06 · sub7 · 읽기만) + +- 원문: `docs/raw/요구_1010_2/사용자요구_1010_2.md` 231 · 시간 근거: `docs/raw/조사/2026-10-16_340_계산시간_측정.md`(아래 「340」) · 계획서: PLAN.md 341 절. +- 결론 한 줄: B05 · B06 은 **이미 한 페이지 · 한 캐시 · 한 [저장]** — 막힌 곳은 「노선」 하나가 그 밖(모달 메모리 → [확인] 76 s 서버 확정 → `location.reload`)에 있는 것. 노선을 ② 초안 칸으로 넣고 계산 묶음 하나(차례 번호 + 취소)를 세우면 배수유역 · 3D 를 뺀 연쇄가 브라우저 몫 0.1 s + 지반 표본 뒤 서버 약 1~2 s 로 줄 전망. + +## 1. 지금 — 캐시 · 알림 · 요청 순서 · [저장] + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 근거 | +| --- | --- | --- | +| 한 페이지 | 주소 둘(`#/b05-profile` · `#/b06-section`)이 한 페이지 — 보기만 숨김 · 보임 · 좌측 패널 · 종단도 · 구조물 폼은 한 벌 | `A00_Common/design/design_page.ts:104-267` · `design_shared.ts:1-11` | +| 캐시 열쇠 | `aislo:{pref·draft·result}:{이름}:{프로젝트}[:{노선}]` 한 형식 · 등록표 한 곳 · pref 만 localStorage(계정 동기) · draft · result 는 sessionStorage | `A00_Common/b_page_state.ts:21-22,48-238,262-285` | +| ② 초안(draft) | 관 `pipes` · 구조물 `structures` · 계획고 `alignment-draft`(노선) · 횡단 `crossdesign` · `cutslope` · `berm` · `std-cross` · 조정 4축 등 30여 칸 | `b_page_state.ts:126-210` | +| ④ 결과(result) | `latest`(노선 · 종단 응답) · `section-context` · `section-detail`(1.5 MB) · 기본값 둘 · `routeedit-initial` | `b_page_state.ts:212-237` | +| 노선 편집 상태 | **캐시에 없음** — 노드 · 곡선 · 반경 · 고정 · 되돌리기 전부 모달 메모리 · 닫으면 사라짐(보기 · 고정 · 지형만 pref) | `B05_Profile_UI_RouteEdit.ts:116-144` · `_History.ts:34,81-115` | +| 가게(store) | `useDesignStore` get · set · subscribe — 값은 캐시에 두고 듣는 쪽 표만 모듈에 | `design_store.ts:133-154` | +| 가게 구독 | 듣는 곳 **하나** — `watchDrafts`(구조물 · 관) → 횡단 상세 다시 얹음 · `alignmentDraft` · `sectionDetail` · `selection` 은 듣는 쪽 없음 | `design_structure_status.ts:67-74` · `design_view_cross.ts:572` | +| 화면 사이 알림 | 사건(CustomEvent) 거의 없음(`specpaint` · 모양 고르기 둘뿐) · 실제 알림은 콜백 표 `shared.bindings` — 보이는 보기만(`toView`) · 둘 다(`toAll` = `onPipesChanged` · `onCrossDesignsUpdated`) | `design_shared.ts:95-101,129-166` | +| 횡단 상세 공유 | 같은 객체 참조를 두 보기가 봄 + 세션 사본 · 같은 요청 겹침 막음 | `B06_Section_Section_Store.ts:1-17,84` | +| 계획고 연쇄 | ▲▼ → `applyEdits` → `alignmentDraft` 씀 → `rebuild`(buildAlignment) → 16/120 ms 뒤 `refreshCrossDesigns`(전 측점 TS) → `onCrossDesignsUpdated` → 유토곡선 그림 → haul-plan 0.4 s 뒤 서버 Node · **ts · 0.06~0.2 s(340)** | `design_profile.ts:326-400` · `B06_Section_Cross_Refresh.ts:182,290,306` · `B05_Profile_Api_HaulPlan.ts:21` | +| 3D | 자동 다시 짓기 없음 — 「낡음」표시만 · [3D 업데이트] 단추에서 1.9 s(화면 멈춤) | `design_view_profile.ts:155,304` · `B05_Profile_UI_Corridor.ts:250-264` | +| 배수유역 | 관 고침 · [분석]에만 다시 셈 · `setRoute` 는 그림만 · 계획고와 안 엮임 | `B05_Profile_UI_Drainage_Panel.ts:146-152,435,680-688` | +| 요청 순서 | **`designRequestSeq` 는 코드에 없음**(지침 · 문서에만 · 9da3bce1b 에서 빠짐) · 자리마다 따로 번호 9개(배수 `requestSeq` · haul `sequence` · 횡단 미리보기 `seq` · `structuresRefreshSeq` · `tableSeq` · 노선 띠 `seq` · 추천 `seq` · `terrainTicket` 등) · AbortController 는 시간 초과용뿐 — 새 요청이 옛 요청을 끊지 않음 | 위 각 줄 · `B05_Profile_UI_Drainage_Panel.ts:183,384-397` · `B05_Profile_Api_HaulPlan.ts:44,84` | +| [저장] 한 줄기 | `saveDesign` — 관 → 구조물 → 계획고 → 암거 옵션 → 상단측 → 횡단 차례 · 화면 잠금 오버레이 · 끝나면 서버 재계산(Node 0.2 s 포함 2.2 s) | `design_save.ts:31-38,132-171` · `B06_Section_Server_Calc_Prebuild.py:1-20` | +| [초기화] | 서버 `route/reset` = 초기값 스냅샷 복원(4.6~12 s) → 초안 · 결과 전부 비움 → `location.reload` | `design_reset.ts:30-58` · `B05_Profile_Router_Lifecycle.py:142-291` | +| 노선 [확인] | `POST route/replan` 한 요청이 끝까지 붙잡음(76 s · 배수 60 s) — 노선 작업본 씀 → 체인(solve · 확정 · 배수 · 관 · 측점 · 설계 이월 · B06 확정) → **초기값 다시 뜸** → 화면은 초안 · 결과 전부 비움 → `location.reload` | `B05_Profile_UI_RouteEdit_Apply.ts:48-106` · `B05_Profile_Router_Replan.py:523-619` · `B03_FileInput_Service_Chain.py:405-637` | +| 잠금 막 | 노선 [확인] 막은 모달 상자 안(`inset:0`) — 오른쪽 횡단 칸은 안 덮임 · 취소 없음 · 초시계만 | `_Apply.ts:48-59` · `B05_Profile_UI_Style_RouteEdit.css:12-13,284-295` | +| 떠남 지킴 | B05 · B06 에 떠남 확인 없음 · `hasDrafts` 는 정의만 있고 쓰는 곳 없음 · 노선 모달 [취소]도 묻지 않고 버림 | `b_page_state.ts:549` · `RouteEdit.ts:282-284` | +| 되돌리기 | 둘로 갈림 — 노선 모달 메모리 100단 · 종단은 세션 사진(`alignment-draft` + 옛 `b05:`/`b06:` 열쇠만 · 새 `aislo:draft:` 횡단 칸은 안 찍힘) | `_History.ts:34` · `B05_Profile_UI_Profile_History.ts:16-30` | +| 지반 자료 | 횡단 지반 = 서버 `section-detail` 의 `samples` · 종단 지반 = `profile_alignment.samples` · 노선 편집 중 지반 = `route/elevations`(py) · 브라우저 지형 격자 없음 | `B05_Profile_Engine_Sections_Core.py:346-367` · `B05_Profile_UI_Profile_Alignment.ts:177,447` · `B05_Profile_Router_Terrain.py:79` | +| 브라우저 · 서버 짝 | 노선 폴리라인 `_Curve.ts` ↔ `common_util_route_polyline.py` · 측점 틀 `_Frame.ts` ↔ `Engine_Sections_Core` · 종단 `UI_Profile_Alignment.ts` ↔ `Engine_Grade_Alignment.py` · 횡단 `common_util_cross_design.ts` ↔ `B06_Section_Engine_Design.py` · 유토곡선 = TS 를 서버 Node 로(②) · **노선 풀기(as_planned) · 균형 종단 · 측점 표본 = 파이썬만** | `_Curve.ts:12-20` · `_Frame.ts:4-11` · `Engine_Grade_Alignment.py:5` · `B06_Section_Server_Calc_Node.ts:25-32` | + +## 2. 노선이 B05 본문 · 실시간이 되면 — 3층 · [확인] 의 뜻 + +| 항목 | 지금 | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 노선 = 캐시 칸 | 모달 메모리 · [확인]이 곧 작업본 쓰기 | 등록표에 `route-draft`(draft · project 범위 · 노드 · 곡선 · 반경 · 스냅 · 지형) 한 줄 · 가게 키 `routeDraft` · 편집 모듈이 메모리 대신 가게에 씀 | `b_page_state.ts` · `design_store.ts` · `B05_Profile_UI_RouteEdit*.ts` 5~8 | 노선이 새로고침 · 보기 전환에도 살아남음 · 0 s | 노선 번호(route id)는 [저장] 때마다 새로 남 → 노선 범위(route) 초안은 「초안 노선」에 매일 자리 없음 → 노선 칸만 project 범위 | M | +| [확인] 의 뜻 | 「노선 작업본 쓰기 + 전 체인 + 초기값 다시 뜸」 한 단추 | [확인] 없앰 — 노선도 [저장] 한 줄기 맨 앞 차례(`route` → 관 → 구조물 → 계획고 …) · 서버는 [저장] 때 노선 풀기 · 측점 · 횡단 정본 재계산(배수유역은 3장 sub3 갈래대로 따로) | `design_save.ts` · `B05_Profile_Router_Replan.py`(체인 쪼개 「노선 저장」 길) · `_Apply.ts` 지움 3~5 | [저장] 대기 2.2 s → 약 6~10 s(340: 배수 뺀 노선 뒤 서버 계산) · 노선 조작 자체는 76 s → 0 | 지금 [저장] 차례는 「관 → 구조물」 앞 — 노선이 바뀌면 관 · 구조물 측점이 어긋남 → 노선 맨 앞 · 관 · 구조물 자리 옮김 규칙 필요(물을 거리 3) | M | +| 초기값 = 노선 [확인] 직후 | `refresh_initial_snapshot` 이 [확인]마다 새로 뜸(저장 안 했는데 기준선 바뀜) | 초기값은 **자동설계 체인 직후 한 번만** · 노선 저장은 작업본만 | `B05_Profile_Router_Replan.py:611-613` 1 | — | 사용자가 「추천 노선 고른 것」을 기준선으로 쓰던 길이 사라짐 → 원하면 [기준선으로] 단추 따로(물을 거리 1) · 규칙 바꿀 거리 ① | S | +| 노선 재탐색 잠금 막 | [확인] 76 s 모달 막 · 초시계 | 노선 끌기 · 놓기는 잠금 없음 · 잠금은 [저장] · [초기화] · 「노선 재탐색」(추천 다시 셈 52 s)만 | `_Apply.ts` · `_Recommend*.ts` 2~3 | 76 s 막 → 없음 | 추천 다시 셈도 뒤에서(이미 미리 셈 저장본 있음 · 다시 1.3 s) 돌리면 잠금 0 가능 | S | +| [초기화] | 스냅샷 복원 → 초안 · 결과 비움 → 새로고침 | 그대로 — 노선 초안도 draft 라 `clearDrafts` 가 함께 비움 | 0 | 그대로 4.6~12 s | 초기값을 체인 한 번만 뜨면 [초기화]는 늘 「파일 올린 직후 노선」으로 감 | S | +| 노선 바꾼 채 안 저장하고 떠남 | 모달 [취소] = 조용히 버림 · 페이지 떠남 확인 없음 | 노선이 세션 초안이면 같은 탭 안에선 남음(다른 페이지 갔다 와도) · 탭 닫기 · 프로젝트 바꿈만 잃음 → `hasDrafts` 로 [저장] 미저장 표시 + 떠남 확인(`ui_template_leave_dialog`) | `design_shared.ts` · `router.ts` 또는 `design_page.ts` 2~3 | — | 떠남 확인은 B05 · B06 처음 — 다른 페이지 지침과 같은 모양인지 확인 | S | +| 되돌리기 | 노선 메모리 · 종단 세션 사진(횡단 새 칸 빠짐) 두 갈래 | 한 갈래 — 세션 사진(`B05_Profile_UI_Profile_History`)의 대상 앞머리를 `aislo:draft:` 전부로 · 노선 모달 `_History` 지움 | `B05_Profile_UI_Profile_History.ts:16` · `_History.ts` 2 | Ctrl+Z 하나가 평면 · 종단 · 횡단을 함께 되돌림 | 사진 크기 = 초안 전부(관 · 구조물 포함 수백 KB 가능) · 100단이면 메모리 확인 · 끌기 중간은 안 찍고 놓을 때만 | M | +| 노선 바뀜과 다른 초안 | [확인]이 모든 초안을 버림(`std-cross` 까지 — 등록표 주석은 「초기화에서만 버림」) | 노선이 바뀌어도 초안은 남김 — 측점 키(0.01 m) 초안은 새 측점에 가까운 것으로 옮기거나 버림을 칸마다 정함 | `B06_Section_Section_Drafts.ts` · `b_page_state.ts` 표 2~4 | 노선을 조금 옮겨도 횡단 손질이 살아남음 | 측점 키가 누가거리라 노선 길이가 바뀌면 뒤 측점이 전부 밀림 → 「XY 로 다시 맞춤 · 허용 거리」 규칙 필요(물을 거리 3) | M | + +## 3. 한 상태를 보는 구조 — 지금에서 가장 작은 변경 + +| 항목 | 지금 | 바꾸면(방법) | 손댈 파일 | 효과 | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 한 저장소 | `design_store` 이미 있음(get · set · subscribe) · 듣는 곳 하나 | 새 저장소 만들지 않음 — 가게 키 넷 보탬: `routeDraft`(②) · `stations`(④ 측점 · 지반 표본) · `profile`(④ buildAlignment 결과) · `generation`(지금 차례 번호) | `design_store.ts` 1 · `b_page_state.ts` 1 | 평면 · 종단 · 횡단 · 유토곡선 · 배수 · 3D 가 같은 창구 | ④ 결과를 세션에 다 쓰면 1.5 MB 상세가 끌기마다 직렬화 → 결과 칸은 메모리 우선 · 세션은 멈춘 뒤 한 번 | S | +| 바뀜 알림 | 콜백 표(`bindings` · `toView`/`toAll`) | 듣는 쪽을 `store.subscribe` 로 옮김 — 평면(노선 칸) · 종단(`profile`) · 횡단(`stations` · `profile`) · 유토곡선(횡단 면적) · 배수(`routeDraft` → 「낡음」표시만) · 3D(「낡음」표시만) · 숨은 보기는 낡음 표만 세우고 보일 때 그림(`host.onShow`) | `design_view_profile.ts` · `design_view_cross.ts` · `design_profile.ts` · `design_shared.ts` 4~6 | 화면 사이 동기화 코드 줄어듦 | `toAll`/`toView` 를 한 번에 다 옮기지 말고 노선 · 측점 두 칸부터 | M | +| 평면 자리 | 모달 상자 | 마 sub5 갈래(배치) — 상태 쪽은 「편집 모듈이 모달이 아니어도 가게만 보면 됨」만 맞추면 됨 | (sub5) | — | 모달 열 때 받는 `route/plan` · 지형 · 배수 층 7 요청(0.45 s)을 페이지 첫 열기에 합침 → B05 첫 열기 +0.4 s 가능 | — | + +## 4. 실시간 계산 묶음 — 차례 · 끊기 · 한 벌 코드 + +| 단계 | 지금(자리 · 시간) | 바꾸면(계산 자리 ①②③) | 손댈 파일 | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 0 차례 번호 | 자리마다 번호 9개 · 끊기 없음 | `design_pipeline.ts` 하나 — 노선 · 계획고 조작마다 `generation += 1` · 단계마다 번호 확인 · 서버 요청은 AbortController 로 옛 것 끊음(규칙의 `designRequestSeq` 를 실제로 세움) | 새 1 · 부르는 자리 3~4 | 새 조작이 오면 앞 계산 즉시 버림 | 끊긴 요청이 서버에선 계속 돎(파이썬 to_thread) → 무거운 단계는 서버도 번호 확인 | M | +| 1 노선 폴리라인 | 브라우저 `_Curve.ts` ↔ py 짝(①) · 3~5 ms | 그대로(①) | 0 | 끌기 중 즉시 | — | S | +| 2 측점 | 브라우저 `_Frame.ts` ↔ py 짝(①) · 서버 재생성 1.5 s | 끌기 중 · 놓을 때 브라우저(①) · 서버는 [저장]에서 검산 | 0~1 | ms | 측점 스냅 · 구조물 측점 규칙이 TS 쪽에 다 있는지 거울 시험 확인 | S | +| 3 지반 표본(종단 · 횡단) | 서버만(py · section-detail 1.5 MB · elevations 0.07 s · 측점 재생성 안 1.5 s) | 아 sub8 갈래 — 갈래 A: 지형 격자를 브라우저로(② · 0 왕복) · 갈래 B: 놓을 때 서버 `cross-preview` 꼴 일괄 표본(③ · 최신만 · 뒤에서) | (sub8) · 파이프라인 1 | A: ms · B: 놓은 뒤 약 1~2 s(추정 · 340 측점 재생성 1.5 s 근거) | B 는 「조작 중 왕복 금지」와 부딪힘 → 규칙 바꿀 거리 ③ | M~L | +| 4 종단 | `buildAlignment` ts ↔ py 짝(①) · 0.9 ms · 계획고 초안은 누가거리 키 | 그대로(①) · 노선이 바뀌면 계획고 편집(`station_offsets` 키 = 누가거리)을 옮길 규칙 | `B05_Profile_UI_Profile_Alignment.ts` 1 | ms | 노선이 바뀌면 처음 계획선을 어디서 얻나 — 지금은 서버 solve · 균형 종단(py 만 · 2~4 s) → 물을 거리 2 | M | +| 5 횡단 | `refreshCrossDesigns` 로컬(①) · 전 측점 88 ms | 그대로 · 표본(3)이 오면 부름 | 0~1 | 0.1 s | 측점 수가 바뀌면 상세 객체(`Section_Store`)를 갈아끼워야 함 — 지금은 「제자리 갱신」 전제 | M | +| 6 유토곡선 | 화면 TS 0.4 ms · 배분 haul-plan 서버 Node(②) 0.13 s · 0.4 s 뜸 | 그대로(②) · 낡음 판정 고침 | `B05_Profile_UI_Profile_Preview.ts` · `B05_Profile_Api_HaulPlan.ts` 2 | 1초 안 | **지금도 「다시 계산하는 중」에 머무는 흠**: 같은 낡은 측점이면 열쇠가 같아 다시 안 부름(`Preview.ts:42-45,67`) · haul-plan 실패한 열쇠는 다시 안 보냄(`HaulPlan.ts:106-107`) — 나 sub2 갈래와 겹침 | S | +| 7 배수유역 · 3D | 배수 60 s(py) · 3D 1.9 s(ts 화면 멈춤 · 서버 Node 짝 ②) | 늦게 — 노선 바뀌면 「낡음」만 · 배수는 다 sub3(자동 · 수동) · 3D 는 열 때 · 멈춘 뒤 | (sub3 · sub5) | 연쇄에서 빠짐 | 3D 를 웹 워커로 돌리면 멈춤 없음(② 같은 코드 그대로) | M | +| 8 [저장] 검산 | 서버 재계산 2.2 s(Node 포함) | 노선 · 측점 · 표본 · 종단 · 횡단을 서버가 다시(①②) — 브라우저 값 안 받음 | `design_save.ts` · `B05_Profile_Router_Replan.py` · `B06_Section_Router_Confirm.py` 3 | 약 6~10 s 잠금(배수 빼고) | 브라우저 표본(갈래 A)과 서버 표본이 다르면 저장 뒤 숫자가 바뀜 → 같은 격자 · 같은 보간 거울 시험 | M | + +## 5. 규칙 바꿀 거리 (CLAUDE.md 5장) + +| 번호 | 규칙 지금 | 부딪힘 | 바꿀 안 | +| --- | --- | --- | --- | +| ① | 초기값 = 「자동설계 체인 직후 · **노선 [확인] 직후**」 | [확인]이 없어지면 그 자리가 없음 · 지금도 저장 안 한 노선이 기준선이 됨 | 초기값 = 자동설계 체인 직후만(원하면 [기준선으로] 따로) | +| ② | 잠금 오버레이 = [저장] · [확정] · [초기화] · **노선 재탐색** | 노선 조작이 실시간이면 노선 쪽 잠금이 없어야 함 | 「노선 재탐색」 → 「노선 추천 다시 셈」만(저장본 있으면 잠금 없음) | +| ③ | 조작 중은 브라우저가 같은 코드로 즉시(**네트워크 왕복 금지**) | 지반 표본이 서버만 — 갈래 A(브라우저 지형) 전까지 왕복 필요 | 「표본만은 뒤에서 서버(최신만 · 끊기)」 허용 줄 하나 또는 아 sub8 갈래 A 확정 | +| ④ | 조작 응답 — 최신 응답만 채택 · **`designRequestSeq`** | 코드에 그 이름 없음 · 자리마다 번호 9개 · 끊기 없음 | 「계산 묶음 차례 번호(generation) + 옛 요청 끊기」로 고쳐 적음 | +| ⑤ | 정본의 자리는 값을 낳은 주인 — 노선 시설은 `pipe_points.json` · `structures.json` | 노선이 실시간으로 움직이면 누가거리 키 시설이 밀림 | 시설 자리 = XY 기준 · 누가거리는 파생(물을 거리 3 답에 따름) | + +## 6. 사용자에게 물을 거리 + +1. 노선을 [저장]으로 확정하면 「노선 [확인] 직후 초기값 다시 뜸」을 없애고, 초기값은 파일 올린 직후 한 번만 — **추천: 예**(원하면 [기준선으로] 단추 따로). +2. 노선을 옮기면 계획고(종단)는 — (가) 누가거리 그대로 두고 지반만 새로 · (나) 매번 균형 종단 새로 셈(서버 2~4 s) — **추천: (가)** · 새 계획선은 [계획선 다시 셈] 단추로. +3. 노선을 옮기면 관 · 구조물 · 횡단 손질은 — (가) 가까운 XY 자리로 따라감(허용 거리 밖이면 버리고 알림) · (나) 전부 버림(지금과 같음) — **추천: (가)**. +4. 노선 · 종단 · 횡단 되돌리기(Ctrl+Z)를 한 줄로 합침 — **추천: 예**. +5. B05 · B06 에서 저장 안 하고 떠날 때 확인 창 — **추천: 예**(탭 닫기 · 프로젝트 바꿈 때). + +## 7. 남의 갈래에 쓸 자리(깊게 안 봄) + +- 가 sub1: [확인] 체인 쪼개기 — `B03_FileInput_Service_Chain.py:405-637`(`run_redesign_chain`) · 노선 풀기 `B05_Profile_Engine.py:109-119` → `Engine_AsPlanned.py:59`. +- 나 sub2: 유토곡선 머묾 두 자리 — `B05_Profile_UI_Profile_Preview.ts:42-45,67` · `B05_Profile_Api_HaulPlan.ts:106-107` · `B06_Section_Cross_Refresh.ts:433-435`(측점 계산 실패를 건너뜀). +- 다 sub3: 배수는 지금도 노선 · 계획고와 안 엮임(`Drainage_Panel.ts:680-688`) — 「낡음」표시 자리만 보태면 됨. +- 라 sub4: 노선 [확인] 뒤 `refresh_initial_snapshot` 이 코리도 없이 뜸(재계획 체인이 코리도 미리 짓기를 안 부름 · `Service_Chain.py:326-328` 은 자동 체인에만). +- 마 sub5: 노선 모달 막은 상자 안만 덮음(오른쪽 칸 안 덮임 · `RouteEdit.css:284-295`). +- 아 sub8: 지반 표본이 브라우저로 오면 3 단계 왕복 0 · 규칙 ③ 풀림. diff --git a/docs/raw/조사/2026-10-16_341_부록8_지형표본.md b/docs/raw/조사/2026-10-16_341_부록8_지형표본.md new file mode 100644 index 000000000..2434cc97c --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_부록8_지형표본.md @@ -0,0 +1,98 @@ +# 341 아 · 지형 표본(지반선) — 브라우저 실시간 표본 가능성 (요구 231 · 읽기만 · sub8) + +- 결론: **지형 표본은 막힘이 아님** — 서버 표본 자체 1~2 ms(열기 20 ms) · 브라우저로 옮겨도 같은 값(차 3e-13 m · 유효 판정 어긋남 0) · 격자 통째 1.4 MB. +- 실측 자리: 검증_sub8 저장본(용화 · 노선 1,078 m · 측점 55~66) · 서버를 띄우지 않고 같은 서버 코드를 직접 불러 잼 · 바꾼 값 없음 · 시험 조각은 세션 임시 폴더(저장소 밖). +- 남의 갈래 쓸 자리: 가(평면→종단) · 나(종단→횡단) 가 브라우저 측점 · 횡단 만들 때 이 표본기를 씀 · 라(영구저장) 가 격자 파일 저장 · 덮어쓰기를 가져감. + +## 1. 노선이 바뀌면 다시 필요한 지형 값 — 지금 + +공용 표본기 하나 = `common_util/common_util_surface_sampler.py:151` `build_surface_sampler` → `DtmGridSampler.sample_xy`(:92). + +- 원본: `storage/…/B04_PreProcess/models/dtm_{필터}[_smooth].npz`(x · y · z · valid_mask) — 1 m 격자(`config_system_terrain.py:108,141`). +- 보간: 쌍선형(scipy `RegularGridInterpolator` linear · 밖 = NaN, :83). +- 빈칸: 둘레 네 칸이 모두 유효할 때만 유효(:100-114) · 임의 표고로 안 메움 · 격자 마지막 선 위 점도 무효. +- 메모리 저장 없음 — 부를 때마다 npz 를 다시 염(열기 20 ms · 수치지형도 격자 74~92 ms). +- 이 프로젝트 설계 지형 = `classification` · DTM · 평활(저장된 종단 1,080점과 차 0.0000 m 로 확인). + +| 값 | 자리(파일:줄) | 표본 방식 | 점 수 | 서버 시간(실측) | +| --- | --- | --- | --- | --- | +| 종단 지반선 | `B05_Profile_Engine_Sections_Core.py:365-367` `generate_sections` | 공용 표본기 · 1 m 간격(`config_system_design.py:255`) | 1,080 | 0.5 ms | +| 측점 지반고(꺾인 곳 · 측점) | `B05_Profile_Engine_Grade.py:275-294` `ground_profile` | 1 m 종단 표본을 선형 보간(격자 다시 안 읽음) · 측점 20 m(`:249`) | 66 | 무시할 만함 | +| 횡단 지반선 | `Sections_Core.py:425-438` | 공용 표본기 · 좌우 ±20 m · 0.5 m(`config_system_design.py:253-254`) · 측점당 81점 | 5,786(측점 66) | 1.0 ms | +| 횡단 덧붙임(성토 끝이 땅에 안 닿을 때) | `B06_Section_Engine_SampleExtend.py:61-109` `extend_unclosed` | 공용 표본기 · 열린 쪽으로 5 m 씩 · 상한 없음 · 무효 만나면 멈춤 | 측점마다 몇 점 | 작음 | +| 종 · 횡단 생성 전체 | `generate_sections` | 위 셋 + 측점 틀 · 확폭 | — | **열기 20 + 생성 21 ms** | +| 높이 띠 · 구간 재기 · 기울기 | `B05_Profile_Router_Terrain.py:79` `/route/elevations` | 공용 표본기 · 20 m(`ProfileStrip.ts:27,58`) / 2 m(`Measure.ts:32`) · 최대 4,000점 | 수십 | **API 0.07 s**(340) — 표본 1 ms · 나머지 = 요청 · DB · 파일 열기 | +| 횡단 미리보기 | `Router_Terrain.py:140-220` `/route/cross-preview` | `generate_sections` 통째 + `compute_cross_design` | 노선 전체 | 약 0.05 s + 요청 | +| 종단 미리보기 · 노선 추천 | `B05_Profile_Engine_RouteInitial_Profile.py:67-125` `/route/profile-preview` | **2 m 비용면**(1 m 격자 한 칸 건너 · 빈칸 = 평균 표고 · `Solver.py:178-257`) · 유효는 가장 가까운 칸 | ±60 m · 241점/측점 | 340 미측정 | +| 구조물 · 관 자리 횡단 | `B05_Profile_Engine_Sections.py:524-609` `sample_structure_sections` | 공용 표본기(종 · 횡단과 같음) | 81/자리 | 작음 | +| 배수 노선 높이 · 관 자리 | `common_util_route_profile.py:149-173` `_sample_z` | 공용 표본기(꼭짓점만 · 3순위) + 선형 | 꼭짓점 | 작음 | +| 노선 꼭짓점 z | `B05_Profile_Engine_AsPlanned.py:49-56` `_z_at` | **한 칸 값(위 칸 쪽 · 보간 없음)** · 밖 = 가장자리 칸 · 빈칸 = 0.0 · valid_mask 안 봄 | 꼭짓점 | 작음 | + +읽을 거리: +- [확인] 76 s 중 지형 표본은 0.1 s 안 — 막는 것은 배수유역(다 갈래). +- 노선 점 놓기 0.07 s 도 거의 요청 왕복 · DB 조회 · 파일 다시 열기. +- 같은 노선인데 값이 갈리는 자리 셋 — 종단 미리보기(2 m 비용면) · 꼭짓점 z(위 칸 · 0.0) · 측점 지반고(종단 표본 보간) 대 측점 `center_z`(격자 직접). + +## 2. 브라우저가 이미 받는 지형 자료 + +**높이 격자를 받는 곳 없음** — 모두 미리보기 메시 · 등고선 · 서버가 표본한 배열. + +| 자료 | 받는 곳(파일:줄) | 꼴 · 해상도 | 범위 | 저장 | +| --- | --- | --- | --- | --- | +| 3D 지형 메시 | B04 `TerrainViewer.ts:401-405` · B05 `B05_Profile_UI_Viewer.ts:442-451` · 미리 받기 `b_asset_cache.ts:372` | GLB · 꼭짓점 50만 넘지 않게 성기게(`Engine_ModelContext.py:366-375`) — 1 m 보다 거침 · 이 현장 7.6~18 MB | 현장 전체 | IndexedDB + ETag | +| 등고선 | B04 `TerrainViewer_Contours.ts:46` · B05 `Viewer.ts:325` · 노선 편집 `RouteEdit_Contour.ts:72` | JSON · 1 m 격자에서 뽑은 선 · 6.7~14.9 MB | 현장 전체 | IndexedDB | +| 점구름 | B04 `B04_PreProcess_UI_Page.ts:496` | JSON · 무작위 50만 점 · 28 MB | 라이다 전체 | **안 함**(매번 받음 · 340 의 B04 113 MB 까닭 하나) | +| 도엽 등고선 | B04 `UI_MapViewer.ts:480` · B05 `Drainage_Parts.ts:378` | GeoJSON(경위도) · 37 MB 표시본 | 도엽 | IndexedDB | +| 종 · 횡단 지반선 | B05 · B06 `B06_Section_Section_Store.ts:93` `/sections/{rid}/detail` | JSON · 1 m · 0.5 m · ±20 m · 1.5 MB | 노선 띠 | 메모리 + sessionStorage | +| 3D 길 모형 | B05 `UI_Corridor.ts:81` | 설계 리본 JSON 15.6 MB(지형 아님) | 노선 | IndexedDB(해시) | + +- 브라우저 표본기 하나 있음 = `TerrainHeightIndex.heightAt`(`B05_Profile_UI_Corridor_Terrain.ts:108`) — 미리보기 메시 위 삼각형 보간 · 1 m 격자보다 거칠고 네 칸 규칙 없음 → **서버 값과 다름 · 지반선 정본 대용 불가**(3D 그림 전용으로 둠). +- 노선 편집 창은 높이를 브라우저에서 한 번도 안 셈 — 모두 서버 호출(`Api_Replan.ts:38,185,230,255`). +- 쌍선형 격자 표본 TS 짝 없음 · 측점 틀(`_interpolate_xy` · `_tangent_at` · 스냅)은 이미 짝(`B05_Profile_UI_RouteEdit_Frame.ts` · 거울 시험 `test_b05_routeedit_frame_mirror.py` · `test_224_2_station_snap.py`) · 횡단 한 줄 보간도 짝(`common_util_cross_design.ts:254` ↔ `B06_Section_Engine_Design.py:121`). + +## 3. 브라우저 실시간 표본 길 — 실측 + +시험: 서버 `DtmGridSampler` 를 JS 로 옮긴 40줄(축 이진 탐색 = `searchsorted(side=right)-1` · 네 칸 유효 · 쌍선형)을 Node 에서 돌려 서버 값과 대조(저장 종단 1,080 + 횡단 5,786 + 격자 둘레 ±5 m 밖까지 무작위 2만 점). + +| 재는 것 | 값 | +| --- | --- | +| 서버와 차 | **최대 3.4e-13 m** · 유효/무효 어긋남 **0 / 26,866** | +| 표본 시간(노선 6,866점) | **0.7 ms**(Node · 데워진 뒤) · 2만 6천 점 5.2 ms | +| 격자 통째(평활 · 835×601 · f32 + 유효 비트) | 2.0 MB · 압축 **1.4 MB** · 100 Mbps 0.11 s · localhost 무시 | +| 노선 띠 ±25 / ±50 / ±100 m | 압축 0.16 / 0.31 / 0.54 MB | +| 수치지형도 격자 통째(1836×1030) | 7.6 MB · 압축 5.7 MB · 띠 ±100 m 0.7 MB | +| cm 정수로 줄이면(u16) | 0.37 MB 지만 값이 ±5 mm 갈림 → **정본과 같은 값 깨짐 · 안 씀** | + +주의: +- 축이 float32 로 저장돼 칸 폭이 0.97~1.09 m 로 고르지 않음 → TS 는 「(x−x0)/1 m」 셈 금지 · 축 배열을 받아 이진 탐색(서버와 같은 결과를 낸 방식). +- 표현이 DTM 이 아닌 프로젝트(TIN · NURBS · 암묵 · meshfree, `surface_sampler.py:167-220`)는 같은 코드로 못 따라함 → 그때만 서버 표본으로 물러섬. +- 횡단 덧붙임(상한 없음)이 ±20 m 밖을 읽음 → 띠를 받으면 띠 끝이 서버의 「지형 끝」과 다른 자리에서 멈출 수 있음 → **이 현장 크기면 통째가 맞음**. + +## 4. 표 — 바꾸는 길 + +| 항목 | 지금(파일 · 함수 · py/ts · 시간) | 바꾸면(방법) | 손댈 파일(대략 수) | 효과(시간) | 위험 · 확인 거리 | 크기 | +| --- | --- | --- | --- | --- | --- | --- | +| 격자 표본기 | 서버만 · `common_util_surface_sampler.py:92` · py · 1 ms + 열기 20 ms | **① 짝** — TS `DtmGridSampler` 40줄 · 두 파일 머리에 짝 표시 · 거울 시험(서버 값 = TS 값 · 가장자리 · 빈칸 · 마지막 선) | 새 TS 1 · py 머리말 1 · 새 시험 1 (3) | 표본 0.07 s(요청) → 1 ms 안 | 축 고르지 않음(이진 탐색 필수) · DTM 아닌 표현은 서버로 물러섬 | S | +| 격자 내려받기 | 없음 | 새 통로 `GET /surface/models/{mid}/grid?smooth=` — 원시 f32 + 축 + 유효 비트 · `cached_file_response`(ETag) · `fetchCachedBytes`(IndexedDB) · B05 미리 받기에 한 줄(`b_asset_cache.ts:359`) | 라우터 1 · 미리 받기 1 · TS 읽기 1 (3) | 첫 받기 1.4 MB(100 Mbps 0.11 s) · 다음부터 0 | npz 를 그때그때 풀지 · 전처리 때 .bin 을 써 둘지(라 갈래 영구저장) | S | +| 높이 띠 · 구간 재기 · 기울기 | `/route/elevations` · `ProfileStrip.ts:58` · `Measure.ts:203,340` · `Slope.ts:122` · py · 0.07 s | 브라우저 표본기로 바로 · 요청 없앰 | 3~4 | 0.07 s → 1 ms 안 · 끌기 중에도 띠가 따라옴 | 분석 지형 = 수치지형도 고르면 격자 하나 더(5.7 MB 또는 띠) | S | +| 종 · 횡단 지반선(편집 중) | [확인] 뒤 서버 `generate_sections` · py · 40 ms(체인 안) | 가 · 나 갈래가 브라우저 측점 · 횡단을 지을 때 이 표본기로 지반선(종단 1,080 + 횡단 5,786점 0.7 ms) · [확인] · [저장] 은 서버가 정본으로 다시(5장) | 이 갈래 몫 0(표본기만 냄) · 가 · 나 쪽 | 노선 고침 → 지반선 1 ms 안 | 확폭 · 측점 스냅 · 구조물 측점 병합까지 TS 가 같아야 같은 자리 표본(가 · 나 확인) | — | +| 횡단 덧붙임 | `extend_unclosed` · py | 같은 표본기 · 통째 격자라 끝 판정이 서버와 같음 | 나 갈래 | — | 띠를 쓰면 어긋남 → 통째 | — | +| 구조물 · 관 자리 높이 | `sample_structure_sections` · `_sample_z` · py | 화면 미리보기는 브라우저 표본 · 저장은 서버 | 가 · 다 갈래 | 요청 없앰 | 배수 노선 z 3순위 규칙은 서버에 둠 | — | +| 종단 미리보기 · 추천 점수 | `/route/profile-preview` · 2 m 비용면 · py | 실시간 화면 값은 1 m 쌍선형 하나로 · 추천 점수(비용면)는 그대로 | 1~2 | 편집 화면 값 = [확인] 뒤 값 | 지금도 편집 미리보기와 확정 종단이 갈림 — 고칠지 물음 3 | S | +| 노선 꼭짓점 z | `AsPlanned._z_at` · 한 칸 · 빈칸 0.0 | 공용 표본기로 바꿈(서버 한 줄) | 1 | 값 통일 | 0.0 이 배수 대체값 ②로 흘러감 · 바꾸면 기존 결과 조금 바뀜 — 물음 3 | S | +| 노선이 격자 밖 | 서버 = 무효(`valid=false` · 표고 null) | 통째 격자라 브라우저도 같은 무효 · 띠 넘음 없음 · 큰 현장(격자 압축 10 MB 넘음)만 띠 ±100 m + 노선이 띠 끝 30 m 안에 들면 다시 받기 | 띠 쓸 때만 +1 | — | 큰 현장 기준 크기 정할 거리 | S | +| 지형 갱신(전처리 다시) | npz 를 덮어씀 · 파일 ETag(수정시각 · 크기, `common_util_http_cache.py:20`) | ETag 따라 새로 받음 · 단 `fetchCachedBytes` 는 **옛 저장본을 먼저 내고 뒤에서 확인**(`b_asset_cache.ts:248`) → 주소에 `manifest.json` 의 `config_signature` · `smoothing_signature` 를 붙여 첫 번에도 새 격자 | 0(주소 만들 때 한 줄) | 옛 지형으로 한 번 그리는 일 없음 | 설계 지형 확정(surface confirmed)이 바뀌면 화면 캐시 비움 · 측점 다시(라 · 사 갈래) | S | +| 저장 자리 | — | 격자 = 파생 자료 · 3층(초기값 · 작업본 · 캐시) 밖 · 서버 `models/` 에 영구 · 브라우저 IndexedDB | — | — | sessionStorage 에 넣지 않음(1.4 MB · 포트별) | — | + +## 5. 5장 규칙과 맞춤 + +- 계산 자리 = **① 파이썬 · TS 짝**(표본기) — 서버 정본 코드 그대로 두고 TS 거울 · 거울 시험으로 값 같음을 묶음. +- 조작 중 = 브라우저 즉시 · [확인] · [저장] · [확정] = 서버가 같은 공식으로 다시(브라우저 값 받아 적지 않음) — 지금 규칙 그대로. +- 자동저장 없음 · 잠금 오버레이 늘지 않음. +- 규칙 바꿀 거리: 없음. + +## 사용자에게 물을 거리 + +1. 브라우저가 받을 지형 — **격자 통째(이 현장 1.4 MB · 추천)** 대 노선 띠(±100 m 0.5 MB · 노선이 나가면 다시 받기). 추천: 통째 · 큰 현장만 띠. +2. 노선 편집의 「분석 지형」(라이다 · 수치지형도 고르기) 실시간에도 둘지 — 수치지형도는 격자가 큼(5.7 MB). 추천: 고를 때만 그 격자를 받음. +3. 같은 노선인데 값이 갈리는 옛 자리(종단 미리보기 2 m 비용면 · 노선 꼭짓점 z 빈칸 0.0) — 실시간 화면은 1 m 쌍선형 하나로 맞출지. 추천: 맞춤 · 노선 추천 점수(비용면)만 그대로. diff --git a/docs/raw/조사/2026-10-16_341_실시간연동_검토.md b/docs/raw/조사/2026-10-16_341_실시간연동_검토.md new file mode 100644 index 000000000..fdb3d82ba --- /dev/null +++ b/docs/raw/조사/2026-10-16_341_실시간연동_검토.md @@ -0,0 +1,233 @@ +# 341 실시간 연동 방향 검토 — 평면(노선 편집) · 종단 · 횡단 · 유토곡선 · 배수유역 (요구 231 · 분석만) + +- 원문 = 장부 231(열 줄) · 시간 근거 = `2026-10-16_340_계산시간_측정.md` · 분석 = 여덟 창 코드 읽기 + 부분 실측(코드 고침 없음) · 원자료 = 부록 1~8 · 바깥 근거 = 안티그래비티(폴더 구조와 AI). +- 숫자 = 340 측정(노트북 · 같은 컴퓨터 접속 · ±20%) 또는 이번 실측(다른 창이 같이 돌아 느림 → 비율만 믿음) · 「추정」 = 안 잰 값. +- 새 계획서 = PLAN 342~347(승인 대기 · 미착수). + +| 부록 | 갈래 | 창 | +| --- | --- | --- | +| 1 평면종단 | 노선 편집 조작 · [확인] 체인 단계 · 측점 · 구조물 · 계획고 | sub1 | +| 2 종단횡단 | 횡단 · 유토곡선 · 3D 길 모형 · 유토곡선 머묾 까닭 | sub2 | +| 3 배수유역 | 관경 자동 지정 · 자동/수동 · 60 s 줄이는 길(실측) | sub3 | +| 4 영구저장 | 매번 다시 계산 · 다시 받는 것 29건 | sub4 | +| 5 화면배치 | 3D · 노선 편집 본문 · 노선 추천 칸 · 안 A/B | sub5 | +| 6 하위폴더 | 파일 전수 · 공용 로직 · AI 도움 판정 | sub6 | +| 7 한페이지 | B05 · B06 캐시 · 알림 · 요청 차례 · 3층 · [확인] 뜻 | sub7 | +| 8 지형표본 | 지반선 브라우저 표본(실측 대조) | sub8 | + +## 1. 결론 + +- **실시간 됨** — 노선 점을 놓은 뒤 종단이 다시 보이기까지 0.05~0.12 s · 횡단 · 유토곡선까지 약 0.3 s(배수유역 · 3D 빼고). 지금은 [확인] 76 s + 다시 열기 2~3 s. +- **막는 것은 배수유역 하나** — 실시간 묶음에서 떼어 냄(자동/수동 · 뒤에서). 계산 자체도 60 s → 약 13 s(결과 같음 · 차이 0 칸) → 약 5.5 s(흐름 방향 저장). +- **바탕은 이미 있음** — B05 · B06 은 한 페이지 · 한 캐시 · 한 [저장]. 노선 선 · 측점 · 종단 · 횡단 · 유토곡선 계산은 브라우저 짝이 있음. 빠진 것 = 지형 표본 · 첫 계획선 · 관 자리 따라감 세 짝 + 노선을 캐시 칸으로 + 계산 묶음 하나(차례 번호 · 옛 요청 끊기). +- **먼저 고칠 흠** = 계획선 두 벌(유토곡선 「다시 계산하는 중」 머묾의 원인 · 재현됨) — 실시간이 되면 같은 흠이 더 늘어남. + +## 2. 요구 열 줄 답 + +| 요구 | 지금 | 바꾸면 | 효과 | 크기 | +| --- | --- | --- | --- | --- | +| 1 3D | 종단 보기 가운데 위 상주 · 늘 그림 | 큰 모달 — 처음 열 때 세움 · 닫으면 멈춤 · 낡았으면 열 때 다시 지음 | 평면 조작 중 3D 그리기 0 · 첫 열기 0.2~0.4 s 줄음 | M | +| 2 영구저장 | 29건 — 저장 없음 · 열쇠 약함 | 입력 지문 열쇠 + 결과 한 쌍(파생 저장본) · 바뀌면 덮어씀 | 같은 파일 재올림 246 s → 44 s 안 · 도엽 3D 면 37 s → 0 · B04 113 MB → 약 1 MB · 3D 1.9 s 멈춤 + 15 MB 올림 → 0 | M~L | +| 3 노선 편집 | 화면 덮는 모달 · [확인] 76 s · 새로고침 | 3D 자리(종단 보기 가운데 위)에 평면 상주 · 왼쪽 「계획노선」 칸 · 편집 단추 지움 | 편집 창 열기 0.54 s · 다시 열기 2~3 s 사라짐 | L | +| 4 노선 추천 | 편집 모달 머리 단추 → 모달 위 모달 | 왼쪽 새 칸 「노선 추천」 — [노선 추천] · 현재 추천 · [초기화] | 단추 자리만 바뀜 · 미리 셈은 그대로 | S~M(3번 뒤) | +| 5 한 페이지 실시간 | 노선만 밖(모달 메모리 → [확인] 76 s → 새로고침) | 노선을 캐시 칸으로 · 계산 묶음 하나 · 평면 → 종단 → 횡단 → 유토곡선 브라우저 즉시 · [저장] 때 서버 정본 | 노선 고침 76 s → 0.3 s 안 | L | +| 6 관경 1000 | 배수유역 유량으로 800~1500 자동 · 시설 종류도 자동(08-17 지시) | 서버 추천 줄 끔 · 1000 은 마스터(구조물정의 배관)에 이미 기본 · 제안은 보임 | 관 값이 배수유역 없이 정해짐 | S | +| 7 배수유역 자동/수동 | 설정 창 없음 · [확인] 체인 안 60 s | ⚙ 설정 창(기본 수동) · 자동 = 3 s 조용하면 뒤에서 · 수동 = 흐림 + [업데이트] · 다시 조작하면 처음으로 | 조작 안 막음 · 계산 13 s → 5.5 s | M | +| 8 하위 폴더 | B05 211 · B06 119 파일 한 폴더 · 앞머리 이름 | 조건부 — 대이동 안 함 · 폴더별 CLAUDE.md 바로 · 화면 없는 계산만 `logic/`(실시간 작업과 함께) | AI 가 화면용 · 서버 묶음용 · 남이 부르는 파일을 경로 · 지침으로 앎 | S → M | +| 9 계획서 | — | PLAN 342~347(승인 대기 · 미착수) | — | — | +| 10 실시간 | — | 3장 표 | — | — | + +## 3. 실시간 묶음 — 노선 점 한 번 놓을 때 + +| 차례 | 할 일 | 지금 | 바뀐 뒤 | 계산 자리 | 시간 | +| --- | --- | --- | --- | --- | --- | +| 1 | 노선 선 | 브라우저 3~5 ms | 그대로 | ① 짝 있음 | 3~5 ms | +| 2 | 측점(일반 · 구조물 · 관) | [확인] 뒤 서버 1.5 s | 브라우저 | ① 짝 있음 + 관 자리 투영 짝 새로 | ms | +| 3 | 지반 표본(종단 1,080 · 횡단 5,786점) | 서버만(띠 요청 0.07 s 왕복) | 지형 격자 1.4 MB 를 한 번 받아 브라우저 표본 | ① 짝 새로(서버와 차 3e-13 m · 유효 어긋남 0/26,866) | 0.7 ms | +| 4 | 첫 계획선 · 사용자 계획고 옮김 | 서버 체인 · 사용자 계획고 버림 | 브라우저 · 바뀐 구간만 다시 맞춤 | ① 짝 새로 | ms | +| 5 | 종단 그리기 | 약 50 ms | 그대로 | — | 50 ms | +| 6 | 전 측점 횡단 설계 · 면적 | 계획고 때만 브라우저 88 ms | 노선 바뀜에도 같은 창구 | ① · ② 짝 있음 | 0.1 s | +| 7 | 유토곡선 · 흙 배분 | 0.4 ms + 서버 Node 0.13 s | 그대로 | ② | 뒤에서 0.13 s | +| 8 | 횡단 카드 그리기 | 바뀐 카드 전부 0.5 s | 보이는 것 먼저 | — | 0.1 s | +| 뒤 | 배수유역 | 체인 안 60 s | 떼어 냄 · 자동/수동 · 뒤에서 | ③ | 조작 안 막음 | +| 뒤 | 3D 길 모형 | 1.9 s 화면 멈춤 | 모달 열린 동안만 · 웹 워커 · 서버 미리 짓기 | ② | 멈춤 0 | +| 저장 | [저장] | 2.2 s(노선은 [확인] 76 s 따로) | 노선부터 서버 정본 다시 · 배수유역 따로 | ① ② ③ | 약 6~10 s | + +- 손에 닿는 시간 = 노선 점 놓고 종단 0.05~0.12 s · 횡단 · 유토곡선까지 약 0.3 s. +- 끄는 동안 = 지금처럼 선만 · 놓을 때 한 번 계산 · 새 조작이 오면 앞 계산 버림. +- 계산 자리 = ① 파이썬 · TS 짝 · ② TS 를 서버 Node 로 · ③ 서버 단독(CLAUDE.md 5장). + +## 4. 배수유역 (요구 6 · 7) + +### 4-1 60 s 줄이는 길(실측 · 결과 같음) + +| 단계 | 지금 | 흐름 방향 한 번 + 판정 한꺼번에 | + 흐름 방향 · 도엽 좌표 저장 | +| --- | --- | --- | --- | +| 도엽 읽기 · 좌표 바꿈 | 3.8 | 3.8 | 0.3 | +| 1차 영역 | 2.6 | 2.6 | 2.6 | +| 흐름 방향 | 29.6(여덟 번 다시 만듦) | 4~5(한 번) | 0.1(읽기) | +| 도로 닿음 판정(열 번) | 22.3(한 칸씩) | 0.5(한꺼번에 · 차이 0 칸) | 0.5 | +| 그 밖 | 2 | 2 | 2 | +| **합(초)** | **60** | **약 13** | **약 5.5** | + +### 4-2 알게 된 것 + +- 배수유역 입력 = 노선 평면 · 도엽 등고선 · 세류선 · 관 자리 · 노선 최저 지반고 — 종단 계획고 · 횡단 조작은 결과를 안 바꿈 → 다시 계산 대상 = 평면(노선) · 관 자리 고침만. +- [확인] 체인이 배수유역을 기다리는 까닭 = 「배수유역 → 관 자리 → 관에 맞춘 종단 계획선」 차례. 관 기본 자리는 격자 없이 나옴(노선 × 세류선) → 이 고리를 끊으면 수동 모드 성립 · [확인] 76 s → 10~16 s. +- 저장된 배수유역에 노선 지문 없음 → 노선이 바뀐 걸 모름 · 지문을 찍어야 「낡음」 표시 가능. +- 관경 기본 1000 은 마스터에 이미 있음 — 서버 추천 줄(`_apply_recommendations` · 관경 · 시설 종류)만 끄면 새 관 = 1000. + +### 4-3 자동/수동 안 + +| 항목 | 안 | +| --- | --- | +| 설정 자리 | B05 · B06 머리 ⚙ → 설정 창 「배수유역 계산: 수동(기본) / 자동」 · 계정마다 기억(지금 설정 모달 없음 · 공용 모달 틀 있음) | +| 자동 | 평면 · 관 자리가 바뀐 뒤 3 s 조작 없으면 서버 계산 → 배수유역 칸만 조용히 바꿈 · 덮개 없음 | +| 수동 | 입력이 낡으면 배수유역 칸만 흐림 + 가운데 [업데이트] → 누른 때 입력으로 계산 → 오기 전엔 칸 구석 「계산 중」 표시만 | +| 다시 조작 | 화면 = 차례 번호 + 요청 끊기 · 서버 = 단계 사이마다 차례 확인해 그만둠 · 늦은 답은 지문이 다르면 버림 | +| 낡은 값 | 응답 · 저장분에 노선 · 관 자리 지문 → 「낡음」 · 낡은 동안 세부 유역 나눔도 멈춤(옛 격자 + 새 노선 섞임 막음) | +| [저장] · [확정] | [저장] = 「낡음」 표시 달고 저장 · [확정] = 서버가 다시 셈 | + +## 5. 화면 배치 (요구 1 · 3 · 4) — 안 A 추천 + +| 자리 | 지금 | 바뀐 뒤 | +| --- | --- | --- | +| 가운데 위(종단 보기) | 3D | 평면(노선 편집 캔버스 · 도구줄 곡선 · 회전 · 잠금 · 재기 · ↶↷ · [3D]) | +| 가운데 위 오른쪽 | — | 선택 측점 횡단 미리보기(접기) | +| 아래 | 종단도 판이 3D 위에 뜸(60vh) | 흐름에 섬(평면 안 가림) · 종단도 + 표 + 유토곡선 · 배수유역도 그대로 | +| 왼쪽 | 구조물 배치 · 페이지 설정 · 계획노선([계획노선 편집]) · 선택 포인트 상세(평소 숨김) | 구조물 배치 · 노선 추천([노선 추천] · 현재 추천 · [초기화]) · 페이지 설정 | +| 3D | 상주 | [3D] → 큰 모달 | +| 횡단 보기 | 횡단 카드 목록 | 그대로 | + +- 안 B(평면 + 오른쪽 패널 셋 · 보기 하나)는 화면 틀이 바뀌어 「배치 · 요소 유지」(231-8)와 부딪힘 → 안 A 뒤 한 걸음으로 갈 수 있음. +- 큰 일 = 노선 편집 모달의 「닫고 새로고침」 수명을 페이지 수명으로 · 되돌리기(Ctrl+Z) 두 벌을 한 벌로 · 편집 값을 메모리 → 캐시 칸으로. +- 차례 = 큰 파일 쪼갬(`design_view_profile.ts` 700줄) → 3D 모달 → 평면 본문 → 노선 추천 칸. +- 3D 노선 점 옮김 · 「선택 포인트 상세」 칸은 저장 안 되는 죽은 길 → 지움 후보. + +## 6. 영구저장 (요구 2) — 효과 큰 차례 + +| # | 항목 | 지금 | 바꾸면 | 효과 | +| --- | --- | --- | --- | --- | +| 1 | 같은 파일 다시 올림 | B04 통째 지우고 전처리 246 s | 지문 같으면 결과 살림 · 「처음부터 다시」 따로 | 246 s → 7~44 s | +| 2 | 도엽 등고선 3D 면 | 열쇠 없이 매번 38 s | 입력 지문 열쇠 · 같으면 건너뜀 | 37 s → 0 | +| 3 | 지표면 모델 행 | 매번 지우고 다시(id 바뀜) → 화면 저장본 빗나감 | 같은 설정이면 id 유지 | 다시 받기 38~83 MB 없앰 | +| 4 | B04 화면 113 MB | 점군 28 MB 매번 무작위 · 브라우저 저장 실패 의심 · 꺼진 층도 받음 | 원인 확인 → 고정 표본 · 켤 때 받음 | 다시 열기 113 MB → 약 1 MB | +| 5 | 3D 길 모형 | 브라우저가 짓고 15 MB 올림 · 서버 검산 없음(5장 규칙 어김) | [확인] · [저장] · [확정] 때 서버 Node 가 지음 | 1.9 s 멈춤 + 15 MB 올림 → 0 | +| 6 | 세부 유역 | B05 첫 열기 11번 · 매 요청 다시 셈 | 한 번에 모아 1번 · 열쇠 맞으면 저장본 | 11번 → 1번 | +| 7 | 지형 표본기 · 비용면 | 요청마다 파일 다시 읽음 | 서버 메모리 기억 | 노선 편집 요청마다 수십~수백 ms(추정) | +| 8 | [확정] · 유토 배분 · 횡단 상세 | 매번 전부 · 1.5 MB 다시 · GET 이 파일 지움 | 입력 지문 · ETag · 지우기는 쓰는 쪽으로 | [확정] 2.2 → 약 0.8 s(추정) | + +- 틀 하나 = 「입력 지문 열쇠 + 결과 한 쌍」(비용면 · 추천 노선에 이미 있는 틀) · 순수 계산 저장본은 `_derived/` 한 폴더 · 종류마다 최근 2벌. +- 전수 29건 = 부록 4. + +## 7. 하위 폴더 (요구 8) — 조건부 + +| 근거 | 값 | +| --- | --- | +| 파일 | B05 ts 149 · B06 94 · B04 18(+ B05 Old 27 · 부르는 곳 0) | +| 맞는 파일 찾기 | 지금도 찾기 한 번에 닿음(앞머리 이름) — 폴더와 무관 | +| 커밋 하나가 손대는 코드 파일 | 중앙 3 · B05 · B06 둘 다 23/50 — 갈래 폴더로 못 줄임 | +| 대이동 비용 | 옮김 261 · 고칠 파일 293 · 시험 문자열 경로 164 · 여덟 창 병행 충돌 · 이력 끊김 | +| 진짜 비용 | 「화면 전용인가 · 서버 묶음에도 들어가나 · 남이 부르나」를 import 를 따라가야 앎 — 서버 묶음이 화면 파일까지 끌어감(corridor 63 · server-calc 52 파일) | +| 공용 로직 | 있음 — 다만 페이지 폴더에 페이지 이름으로(B06 횡단 그림 22 · B04 지도 7 · B05 17) · 같은 보간 7벌 | + +- 판정 = 대이동 안 함 · 폴더별 CLAUDE.md 넷 바로(갈래 지도 · 짝 · 묶음 입구 · 남이 부르는 파일) · 화면 없는 계산만 `logic/` 하위 폴더(실시간 작업의 새 계산부터 · 이미 순수한 43파일은 싱크 직후 한 번) · 파이썬 안 옮김 · 이름 앞머리 그대로. +- 바깥 근거(안티그래비티 · 공식 문서 · 연구 요약) = 하위 폴더 CLAUDE.md 는 그 폴더 파일을 읽을 때 붙음 · 일관된 앞머리 이름은 찾기 한 번에 닿음 · 대량 이동은 병행 작업 충돌 · 이력 끊김 → 「대이동 보류 · 지도 문서로 보완」 — 같은 결론. + +## 8. 먼저 고칠 흠 (분석 중 찾음 · 안 고침) + +| # | 흠 | 영향 | 크기 | +| --- | --- | --- | --- | +| 1 | 계획선 두 벌 — 화면 선(관 지점 0.01 m)과 다시 셈 선(서버 측점 0.001 m)이 2 mm 어긋남 | 유토곡선 「다시 계산하는 중」 머묾 · 흙 배분 안 나감(재현됨) | S | +| 2 | 측점 키 자릿수 섞임(0.01 · 0.001 m) | 측점이 움직이면 횡단 고침이 조용히 버려짐 | M | +| 3 | 「최신 응답만 채택」 차례 번호가 지침엔 있고 코드엔 없음 · 자리마다 번호 9개 · 옛 요청 안 끊음 | 실시간 때 늦은 답이 덮을 위험 | M | +| 4 | 노선 [확인] 체인이 종 · 횡단을 두 번 생성 | 1.5~2 s 헛일 | S | +| 5 | 3D 길 모형 = 브라우저가 짓고 서버는 검산 없이 저장 · [확인] 체인은 안 지음 | 규칙 어김 · 초기값에 옛 3D | M | +| 6 | 노선 [확인]이 관 정본을 지움 | 사용자 관 편집(종류 · 관경 · 자리) 매번 사라짐 | 실시간 작업에서 바뀜 | +| 7 | 노선 [확인] 뒤 초기값이 저장 안 한 노선으로 다시 뜸 | [초기화] 기준이 흔들림 | S | +| 8 | 횡단 상세 GET 이 측점 파일을 지움 | 같은 프로젝트를 둘이 열면 서로 지움 가능 | S | +| 9 | B05 첫 열기 세부 유역 요청 11번 | 340 관찰 원인 | S | +| 10 | B04 브라우저 저장 실패 의심 | 113 MB 다시 받음 원인 후보 | S | +| 11 | 같은 노선인데 값이 갈리는 지형 표본 자리 둘(종단 미리보기 2 m 비용면 · 노선 꼭짓점 z 빈칸 0.0) | 편집 미리보기와 확정 값 다름 | S | +| 12 | 노선 거울 시험이 git 밖(tmp) | 짝이 안 지켜짐 | S | +| 13 | 서버 Node 묶음 낡음 판정이 화면 공용 · 설정 파일을 안 봄 | 그쪽만 바뀌면 묶음 안 다시 지음 | S | + +## 9. 규칙 바꿀 거리 (CLAUDE.md 4 · 5장 · 사용자 확정 뒤) + +| # | 지금 | 안 | +| --- | --- | --- | +| 1 | 초기값 = 자동설계 체인 직후 · 노선 [확인] 직후 | 자동설계 체인 직후만(원하면 [기준선으로] 단추) | +| 2 | 잠금 오버레이 = [저장] · [확정] · [초기화] · 노선 재탐색 | 노선 끌기 · 놓기는 잠금 없음 · 「노선 추천 다시 셈」만(저장본 있으면 없음) | +| 3 | 최신 응답만 채택(`designRequestSeq`) | 계산 묶음 차례 번호 + 옛 요청 끊기 | +| 4 | 조작 중 네트워크 왕복 금지 | 그대로 — 지형 격자를 브라우저로 가져와 지킴 · 배수유역만 「뒤에서 서버(최신만 · 끊기)」 한 줄 | +| 5 | 노선에 놓인 시설 정본 = 누가거리 | 노선이 움직이면 관 · 구조물은 땅 위 자리(좌표) 따라감 · 누가거리는 다시 매김 | +| 6 | 데이터 층 셋 | 넷째 「파생 저장본」(`_derived/` · 결과 옆 열쇠 · 지워도 다시 셈) | +| 7 | (없음) | GET 은 지우지 않음 | +| 8 | 배수유역 격자 원점 = 도로 시작점(07-31 지시) | 좌표 정수 m 고정(흐름 방향 저장용) | +| 9 | (없음) | `logic/` = 화면 · 3D · 요청 · 세션 저장 금지 · 서버 묶음이 부르는 계산은 `logic/` 과 common_util 만 | + +## 10. 사용자 결정 거리 — 추천대로면 답 없이 진행 · 바꿀 번호만 + +평면 · 종단(노선 편집) +1. 노선을 고치면 사용자가 고친 계획고 — **바뀐 구간만 지반에 다시 맞추고 그 밖은 지킴(추천)** / 전부 새로 맞춤(지금) / 비율로 옮김. +2. 노선을 고치면 관 · 구조물 자리 — **땅 위 자리(좌표) 따라감 · 노선에서 멀어지면 알림(추천)** / 구조물 측점 그대로 · 관은 지우고 새로(지금). +3. 노선을 고치면 횡단 손질 — **넘길 칸 일곱(지반 유형 · 측구 종류 · 측구 선택 · 2단 경사 · 암 경계 · 암 경사 · 소단) · 구조물 조정은 구조물 따라 · 단면 유형 · 측구 방향은 새 지형 · 사라진 측점 고침은 버리고 「노선 밖 고침 N 건」 알림(추천)**. +4. 초기값([초기화]가 돌아갈 자리) — **파일 올린 뒤 자동설계 한 번만 · 원하면 [기준선으로] 단추(추천)** / 노선 바꿀 때마다 다시(지금). +5. 노선 [확인] 단추 — **최종은 없앰 · 노선도 [저장] 한 번에(추천)** · 중간 단계 동안은 [노선 반영]으로 남김. +6. 점 놓고 종단 먼저(0.3 s 안) · 횡단 · 유토곡선 그다음(1 s 안) — **예(추천)**. +7. 되돌리기(Ctrl+Z) 평면 · 종단 · 횡단 한 줄 · 저장 안 하고 떠날 때 확인 창 — **예(추천)**. + +화면 배치 +8. 3D — **큰 모달(추천)** / 오른쪽 접는 패널. +9. 배치 — **안 A(3D 자리에 평면 · 횡단 보기 전환 유지 · 추천)** / 안 B(평면 + 오른쪽 패널 셋 · 보기 하나). +10. 노선 추천 칸 자리 — **지운 「계획노선」 자리(추천)** / 맨 위. +11. 3D 노선 점 옮김 · 「선택 포인트 상세」 칸(저장 안 되는 길) 지움 — **예(추천)**. +12. 노선 편집 위 「종단 띠」 — **아래 종단도가 실시간으로 따라오면 지움(추천)**. +13. 3D 다시 짓기 — **모달 열 때 낡았으면 자동 + 서버가 [저장] 때 미리 지음(추천)** / [3D 업데이트] 누를 때만(지금). + +횡단 · 유토곡선 +14. 횡단 카드는 보이는 것 먼저 그림 — **예(추천)**. +15. [전체 측점 반영]이 측점마다 지금 값을 「사용자 선택」으로 박는 동작 없앰(표준만 반영) — **예(추천)**. +16. 다시 셈 뒤에도 낡은 측점이 남으면 — **곡선은 그리고 그 측점만 표시(추천 · 09-03 「새 값만 보여주기」를 바꿈)** / 곡선 숨김(지금). +17. 유토곡선 머묾(계획선 두 벌)을 맨 먼저 고침 — **예(추천)**. + +배수유역 +18. 관경 자동 지정을 끌 때 시설 종류 자동 바꿈(배관 → BOX암거 · 세월교)도 끔 · 제안으로만 보임 — **예(추천 · 08-17 「초기 전처리 계산에서 해당값으로 설정」을 바꿈)**. +19. 이미 놓인 관의 관경(800 · 1200 …) — **그대로 · 새 관만 1000(추천)**. +20. 자동/수동 설정 — **계정마다(추천)** / 프로젝트마다. +21. 다시 계산 대상 — **평면(노선) · 관 자리 고침만(추천 · 종단 · 횡단은 결과를 안 바꿈)** / 종단 · 횡단 조작까지. +22. 자동 모드 조용한 시간 — **3 초(추천)**. +23. 수동 흐림 범위 — **배수유역 칸만(유역도 · 세부 유역 목록 · 관경 제안) · 종단 그림의 관 표시는 그대로(추천)**. +24. 낡은 채 [저장] — **「낡음」 표시 달고 저장 · [확정] 때 서버가 다시 셈(추천)**. +25. 노선 저장 때 관 자리를 배수유역 없이 먼저 정하고 배수유역이 나중에 와도 관 자리는 안 옮김 — **예(추천)**. +26. 흐름 방향 저장을 위해 격자 원점을 도로 시작점 → 좌표 정수 m 고정 — **예(추천 · 07-31 지시를 바꿈)**. + +영구저장 +27. 같은 파일 다시 올리면 전처리 결과 살림 · 「처음부터 다시」는 따로 고름 — **예(추천)**. +28. 서버 「파생 저장본」(지워도 다시 세는 계산 결과)을 데이터 넷째 층으로 · `_derived/` 한 폴더 · 종류마다 최근 2벌 — **예(추천)**. +29. B04 지도에서 꺼진 층은 켤 때 받음 — **예(추천)**. +30. 3D 길 모형은 서버가 짓고 브라우저는 받기만 · 저장 안 한 초안이 있을 때만 브라우저 미리보기 — **예(추천)**. +31. 점군 미리보기 고정 표본 하나(지금은 열 때마다 무작위 50만 점) — **예(추천)**. + +지형 +32. 브라우저 지형 — **격자 통째(이 현장 1.4 MB · 추천)** · 큰 현장만 노선 띠. +33. 「분석 지형」(라이다 · 수치지형도 고르기) — **고를 때만 그 격자 받음(추천)**. +34. 값이 갈리는 옛 표본 자리를 1 m 쌍선형 하나로 맞춤 · 노선 추천 점수만 그대로 — **예(추천)**. + +하위 폴더 +35. 대이동 안 함 · 폴더별 CLAUDE.md 넷부터 — **예(추천)**. +36. `logic/`(화면 없는 계산만) 하위 폴더를 실시간 작업의 계산 자리로 · 이름 앞머리 그대로 — **예(추천)**. +37. B05_Profile/Old 27파일(부르는 곳 0) 지움 — **예(추천 · git 이력에 남음)**. +38. 파이썬 파일은 옮기지 않음 — **예(추천)**. +39. 이미 순수한 43파일 `logic/` 이동은 깃 싱크 직후 · 다른 창 쉴 때 한 창이 — **예(추천)**. + +## 11. 새 계획서 = PLAN 342~347 (승인 대기 · 미착수) + +| 절 | 무엇 | 크기 | 창(안) | 앞 단계 | +| --- | --- | --- | --- | --- | +| 342 | 실시간 앞 — 흠 고침 · 빠른 효과(계획선 한 벌 · 체인 두 번 → 한 번 · 배수유역 빠른 길 · 관경 1000 · 폴더 CLAUDE.md) | S × 5 | sub1 · sub2 · sub3 · sub6 동시 | 없음 | +| 343 | 영구저장(재올림 · 도엽 3D 면 · B04 113 MB · 3D 서버 짓기 · 세부 유역 · 확정 지문) | S~M × 5 | sub4 · sub8 | 없음 | +| 344 | 실시간 바탕(지형 짝 · 첫 계획선 · 관 투영 짝 · 측점 키 · 계산 묶음 · 노선 캐시 칸) | M × 4 | sub8 · sub1 · sub2 · sub7 | 342-1 · (344-4 는 345-3 뒤) | +| 345 | 화면 배치(쪼갬 · 3D 모달 · 평면 본문 · 노선 추천 칸) | L | sub5 차례로 | 없음 | +| 346 | 실시간 연결(평면 → 종단 → 횡단 → 유토곡선 · [확인] 없앰 · [저장] · 되돌리기 · 떠남 확인 · 3D 워커) | L | sub7 · sub1 · sub2 | 344 · 345 | +| 347 | 배수유역 자동/수동(지문 · 체인 떼기 · 설정 창 · 흐림 · 차례 번호 · 흐름 방향 저장) | M | sub3 | 342-3 · 345-3 |