- `docs/` 를 .gitignore 에서 빼 git 추적 대상으로 전환 (위키·완료 이력·검증 기록) - `docs/raw/PLAN.md` · `docs/raw/OWNERS.md` 를 저장소 최상위로 이동 후 .gitignore 에 등록 — 창끼리 공유하되 저장소에는 안 올리는 장부 - 살아 있는 경로 참조 7개 파일 정정 (아카이브 107건은 그때 사실이라 그대로 둠) - graphify 날짜별 산출물(`docs/wiki/graphify-out/20*/`) 제외 — `graphify update` 가 다시 만듦 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
13 KiB
13 KiB
완료 계획서: B05 비정규 측점 테스트 반영 및 후속 작업 (2026-07-24 이관)
1. B05 비정규 측점 테스트 반영 (2026-07-24)
측점 1+0에 곡선, 1+10에 경사 변경 테스트 중 발견. 정적 검사 통과(
tsc/prettier).
- 구배 블록 값 안 보임 → 좁으면 90° 회전 표기: 변화점 추가로 구간이 좁아지면 구배(L/H/S) 값이
가로로 안 들어가 비었음. 이제 값을 항상 표기하되, 가로로 안 맞으면 90도 회전해 블록 폭·행 높이에
맞춰 글자를 줄여 넣음(작아도 표기 우선). →
_UI_Profile_Table.tsbuildSegmentRows(값 span+is-rotated,rowHeight전달),_UI_Style.css. - 비정규 측점 값 열에 구배/곡선 표기: 선택 시 값 열 오버레이의 구배(L/H/S)·곡선(L/R) 칸을 채움 —
구간 안이면 그 구간 값을 그대로(중복 허용), 변화점이라 좌우로 갈리면
좌 / 우로 절반 나눠 가로 표기. 곡선도 동일(해당 chainage 곡선의 L/R). →_UI_Profile_Table.tsbuildIrregularColumn,_UI_Style.css(셀overflow:hidden).
2. B05 후속 — 편집값 세션 유지 · 복원 · Y축 sticky · 비정규 측점 편집
2026-07-24 기획→승인→구현. 정적 검사 통과(
tsc --noEmit기존 B07 무관 오류 제외,prettier). 실제 앱 E2E 미실시. 사용자 결정: 작업1(+작업2 복원) 포함 · 작업3(Y축 sticky, 저위험) 포함 · 작업4·5·6 추가. 아래 체크리스트 모두 구현됨.구현 요약(변경 파일):
- 작업1(편집 이월):
_UI_Profile_Panel.tsrender()— 경로 변경 시store.edited()면 현재 편집을 새 스토어로 이월(store.replace(carried))해 새 base에 재적용. best-effort(미매칭·범위 밖 드롭).- 작업2a(복귀 복원):
_UI_Page.tsrestoreSections— 클라이언트 목록이 빈 경우만detail.longitudinal.stations의kind==="irregular"(+structure)로 사이드바 복원._UI_IrregularStations.tssetStations()신설.B06_..._Api_Fetch.tsSectionStation.structure?추가.- 작업3(Y축 sticky):
B06_..._UI_Longitudinal.tsonYAxis콜백으로 눈금 공유._UI_Profile_Panel.tsbuildStickyYAxis(0크기 sticky 앵커+절대배치 축, 불투명 배경으로 값 누출 차단)._UI_Style.css.- 작업4(z-index):
_UI_Style.css.b05-profile-table__irregular-colz-index 6→4(이름표 5 아래).- 작업5(비정규 편집 버튼):
_UI_Profile_Edit.tscreateEditOverlay에irregularStations추가 → ▲/▼(+원복) 렌더(규칙 측점과 동일adjustStation파이프라인)._UI_Profile_Panel.ts에서 전달.- 작업6(값 열 입력):
_UI_Profile_Table.tsbuildIrregularColumn계획고 셀을no-spin입력으로 →onAdjustStation(chainage, target−plan)._UI_Style.css입력 셀 pointer-events 복구.
상세 작업 체크리스트
작업 1 — 재탐색 시 "사용자 조작값" 유지 (프론트 한정, 백엔드는 확정 때만)
- 문제: 브라우저 새로고침은 결과가 남지만, 경로 변경·재탐색(재계산) 시 사용자가 조작한 계획선 편집(측점 계획고 델타·종단곡선 반경)이 리셋됨. 사용자는 결과가 아니라 조작값이 이어져, 경로가 미세하게 바뀌어도 대부분 재계산되며 편집이 유지되길 원함. 백엔드로는 안 보냄 (확정 시에만 전송).
- 원인(조사): 프로필 편집 스토어가
routeId로 키됨.B05_wf2_Route_UI_Profile_Panel.tsrender()의if (nextRouteId !== routeId || !store.dirty())분기에서, 재탐색으로 새routeId가 오면 스토어를stored?.edits(신규 경로엔 빈 값)로 재생성 → 편집 소실. (비정규 측점은 Page 클라이언트 상태라 재탐색 후에도 유지되므로 이번 대상 아님.) - 핵심 근거: 편집은 chainage 키(
station_offsets[chainage],curve_radii[chainage])라,buildAlignment( base, edits)가 새 경로의 base에 그대로 재적용 가능. 즉 스토어만 안 비우면 이어짐. - 구현 체크리스트:
render()에서 경로 변경 시 현재 편집을 새 스토어로 이월: 재탐색으로routeId가 바뀔 때store.edited()면store.edits()(현재 in-memory 편집)를 새 스토어의 초기값으로 넘기고, 없을 때만stored?.edits(백엔드 저장분/신규 빈 값) 사용.- 이월된 편집을 새
routeId의 세션 초안(sessionStorage)에도 기록해 재탐색 후 새로고침에도 유지. - 새 alignment에 없는 chainage의 편집 처리 확인:
buildAlignment가 미매칭 키를 무시하는지 점검, 필요 시 매칭 chainage로만 프루닝(경로 대폭 변경 시 오적용 방지). - 비정규 측점은 현행 유지 확인(재탐색 후
setIrregularStations재적용) — 회귀만 점검.
- 문제(한계) — 사용자 질문 답변: 편집을 이어붙이는 방식은 chainage 키 기준 best-effort라 완벽하진 않다.
- 측점 계획고 델타(
station_offsets): 규칙 격자(20·40·60…)에 걸리므로 노선이 조금 바뀌어도 격자 chainage는 대부분 그대로 → 잘 유지됨. 단 노선이 짧아지면 범위 밖(끝단 너머) 편집은 드롭 (resolvePvi가 노선 범위 밖 offset을 버림). - 종단곡선 반경(
curve_radii): 키가 자동 변화점(PVI) chainage인데, 재탐색 시 지반 형상이 바뀌면 자동 변화점 위치가 달라질 수 있음 → 옛 변화점 chainage에 맞는 변화점이 새 선형에 없으면 그 반경 편집은 적용 안 됨(무시). 즉 계획고 편집보다 반경 편집이 더 취약. - 의미 드리프트: 노선이 크게 달라지면 같은 offset이 새 지반에선 어색한 결과를 낼 수 있음(그래도 값은 유지). → 결론: “미세 변경 시 이어짐”은 확실히 충족. 대폭 변경 시엔 일부(특히 반경) 편집이 드롭될 수 있고, 이는 chainage 키 방식의 근본 한계라 완전 해결하려면 편집의 의미(어느 변화점/구간인지) 추적이 필요(과대). 이번엔 best-effort로 진행하고, 드롭된 편집은 조용히 버린다(사용자 의도에 부합).
- 측점 계획고 델타(
작업 2 — [검토] 확정 시 저장 위치 정리 + 다음 페이지 이동/복귀 흐름
- 성격: 코드 변경 전 현황 검토·결정. 조사 결과:
- 확정 시 저장(현행): ①
profilePanel.save()→PUT/route/profile-alignment→편집을longitudinal.json에 반영 +grade_summary를 DB(longitudinal_sections.data). ②confirmRoute(...)→비정규 측점 횡단 파일 생성 +longitudinal.jsonstations 병합(파일), 경로 상태CONFIRMED(DB). ③ 편집 세션 초안은markSaved()로 삭제. - 편집 중 프론트 상태: 계획선 편집 = sessionStorage 초안(routeId) + in-memory. 비정규 측점 = in-memory(Page+패널)뿐(확정 전 미영속).
- 복귀 시(현행):
fetchLatestRoute+restoreSections로 편집(=longitudinal.json)·백엔드 비정규 측점은 그래프에 복원됨. 그러나 사이드바 비정규 목록은 미복원(클라이언트 상태 소실 → 편집/삭제 불가).
- 확정 시 저장(현행): ①
- 검토 결과 / 계획:
- (a) 포함(사용자 승인) — 복귀 시 사이드바 비정규 목록을 백엔드에서 복원:
detail.longitudinal. stations중kind==="irregular"(+structure)를 읽어 사이드바 리스트·PageirregularStations재구성. 구현 체크리스트:restoreSections(또는render후)에서 detail의 irregular 측점을 추출 → 사이드바 목록 API로 주입 (신규panel.irregularStations.setStations(...)또는 유사) →applyIrregularStations로 그래프·3D 반영.- 측점번호/잔여거리 역산:
chainage → (측점번호, 잔여거리)는 측점간격으로 환산.
- (b) [백로그 유지] 확정 시 비정규 측점의 DB
cross_sections행 미기입(B07/B08용) — 표시(B06)는 파일 기반이라 정상. 이번 범위 제외, 후속 판단. - (c) 문서화: 확정 데이터 흐름표(무엇이 DB/파일/프론트 어디에)를 완료 후 검증보고서로 남김.
- (a) 포함(사용자 승인) — 복귀 시 사이드바 비정규 목록을 백엔드에서 복원:
작업 3 — [가능성 검토 포함] 하단 패널 그래프 Y축 스크롤 고정(sticky)
- 목표: 가로 스크롤 시 그래프 좌측 Y축(표고 눈금·축선) 고정. 단, 예전 테이블 좌측 여백처럼 스크롤되는 값이 새어 보이면 안 됨(불투명 배경으로 가림).
- 조사/설계: 그래프는 스크롤 컨테이너 안 단일 SVG라 SVG 자체를 sticky 불가. →
.b05-profile__chart안에 별도 sticky 오버레이 div(position: sticky; left: 0, 폭=LONG_PAD.left, 불투명 배경, 상위 z-index)를 두고 표고 눈금 라벨+축선을 그린다. 스크롤 SVG의 좌측 눈금은 이 오버레이가 덮어 가림. - 가능성 판정(사용자 조건: 버튼 중첩·성능 문제면 하지 말 것):
- 편집 버튼은 상/하단(중앙 측점 위)에 있고 Y축은 좌측(0~62px), 0측점 버튼은 ≈90px라 중첩 거의 없음.
- 성능: 정적 오버레이라 부담 없음.
- 주요 난점: 오버레이 눈금이 SVG 격자선과 같은 Y-스케일이어야 함 →
createLongitudinalProfile의 Y-스케일/눈금 계산을 오버레이가 공유하도록 노출/전달 필요(중복 렌더 소지). - 판정: 구현 가능·저위험 → 포함(사용자 승인). 다만 Y-스케일 공유(중복 렌더) 정리가 필요.
- 구현 체크리스트:
createLongitudinalProfile가 Y-스케일(또는 눈금 배열)을 반환하거나, 패널이 동일 스케일로 눈금 계산..b05-profile__chart에 sticky Y축 오버레이(불투명 배경·축선·표고 라벨) 추가, z-index로 값 누출 차단.- 리사이즈·폭맞춤 시 눈금 위치 재동기화 확인.
작업 4 — [버그] 비정규 측점 값 열이 행 제목(sticky 이름표)을 가림 (사용자 3번)
- 문제: 지난 세션 ⑤에서 만든 비정규 측점 값 열 오버레이의 z-index(6)가 sticky 행 이름표(z-index 5)보다 높아, 가로 스크롤로 값 열이 이름표 열 위로 오면 행 제목이 가려짐.
- 계획:
.b05-profile-table__irregular-colz-index를 이름표(5) 아래(예: 4)로 낮춘다. 규칙 값 셀(0)·곡선(2) 보다는 위라 값 열은 정상 표시되고, 좌측 이름표만 항상 위에 남는다.- 스크롤로 값 열이 이름표 영역까지 왔을 때 이름표가 안 가려지는지 확인.
작업 5 — [기능] 비정규 측점도 상/하·시프트 상/하 편집 버튼으로 제어 (사용자 4번)
- 근거(조사):
adjustStation(base, edits, chainageM, delta)+resolvePvi는 노선 범위 내 임의 chainage를station_offset으로 받아 변화점(PVI)으로 승격시킨다 → 비정규 측점의 계획고도 규칙 측점과 똑같이 버튼으로 조정 가능. - 계획:
createEditOverlay에 비정규 측점 목록을 전달하고, 각 비정규 측점 x에 측점 ▲/▼(+원복 ↺) 버튼을 렌더 →adjustStation(base, edits, irregular.chainage_m, ±step)호출(규칙 측점과 동일 파이프라인).- 시프트(구간 ⇧/⇩)는 현행처럼 구간 단위 유지(비정규 측점은 구간 내부에 놓임) — 별도 버튼 불필요, 다만 비정규 측점이 변화점이 되면 그 지점에서 구간이 나뉘는 것을 확인.
- 편집 오버레이 버튼과 값 열(작업4)·측점 라벨이 겹치지 않게 배치 점검.
작업 6 — [제안] 테이블에서 비정규 측점 값 직접 입력 (사용자 5번, 작업5 연계)
- 목표: 버튼(작업5)과 별개로, 테이블 레이아웃을 깨지 않는 범위에서 비정규 측점의 계획고를 직접 입력.
- 제안(권장안): 작업4의 값 열 오버레이 안(테이블 실제 행이 아니라 오버레이라 레이아웃 영향 없음)의
계획고 셀을 숫자 입력으로 바꾼다. 입력 시
현재 계획고 → 목표 계획고차이를 delta로 계산해adjustStation(base, edits, chainage, delta)호출 → 규칙 측점과 동일하게 station_offset으로 반영. 스피너는 제거(no-spin). (곡선이 생기는 변화점이면 곡선 R 셀도 입력 가능하게 확장 여지.)- 장점: 오버레이는 테이블 위에 떠 있어 실제 12행 셀 구조를 안 건드림 → 레이아웃 안전. 값 입력·버튼이
같은
station_offset파이프라인이라 일관. - 선택된 비정규 측점의 값 열 계획고 셀 →
<input type=number no-spin>, change 시 adjustStation. - 입력 폭/정렬이 오버레이 yr 폭 안에 들어오는지(레이아웃 불변) 확인.
- 장점: 오버레이는 테이블 위에 떠 있어 실제 12행 셀 구조를 안 건드림 → 레이아웃 안전. 값 입력·버튼이
같은