From d12e500baf3b3620dcae1c3868e85d022ff0bb25 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Fri, 30 Oct 2026 07:35:16 +0900 Subject: [PATCH] =?UTF-8?q?chore(=EA=B3=84=ED=9A=8D):=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=20452=20=EC=9A=94=EA=B5=AC=EC=84=9C=20=C2=B7=20=EB=B6=84?= =?UTF-8?q?=EC=84=9D=20=EB=91=98=20=C2=B7=20PLAN=20590=20=C2=B7=20591=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20=EB=8C=80=EA=B8=B0=20=E2=80=94=20=EC=98=88?= =?UTF-8?q?=EC=A0=95=EB=85=B8=EC=84=A0=20=EC=A0=80=EC=9E=A5=20=EC=9E=90?= =?UTF-8?q?=EB=A6=AC=20=C2=B7=20=EB=93=B1=EB=A1=9D=20=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=A0=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- .../요구_1025/_분석_452-A_설계내용_폴더.md | 228 +++++++++++++++++ .../_분석_452-B_등록기준점_기준지정통합.md | 238 ++++++++++++++++++ ...요구서_452_예정노선_저장자리_등록기준점.md | 44 ++++ 3 files changed, 510 insertions(+) create mode 100644 docs/raw/요구_1025/_분석_452-A_설계내용_폴더.md create mode 100644 docs/raw/요구_1025/_분석_452-B_등록기준점_기준지정통합.md create mode 100644 docs/raw/요구_1025/요구서_452_예정노선_저장자리_등록기준점.md diff --git a/docs/raw/요구_1025/_분석_452-A_설계내용_폴더.md b/docs/raw/요구_1025/_분석_452-A_설계내용_폴더.md new file mode 100644 index 000000000..df2f611f8 --- /dev/null +++ b/docs/raw/요구_1025/_분석_452-A_설계내용_폴더.md @@ -0,0 +1,228 @@ +# 요구 452-A — 예정노선 설계 내용 = 프로젝트 폴더 · 조사 + +- 근거 = 요구 452(사용자 확정 ①~⑤) · `docs/raw/요구_1025/_분석_451_예정노선_영구저장.md`. +- 실측 = 랩탑 메인 storage · DB(읽기 전용 트랜잭션) · 2026-10-30. 코드 · git · storage · DB 고침 없음. + +## 0. 한눈에 + +- 화면은 DB 를 직접 안 봄 — API 꼴을 그대로 두면 화면 고칠 곳 0(위성 「한 장짜리」 걷음만 화면 넷). +- 설계 내용 한 벌 = 새 파일 `D03_PlanAnalysis/plan_network.json`(지점 · 선 · 마크 · 조각 · 연도 · epsg 하나) · 길이 · 측점 · 조각 좌표는 읽을 때 `derive()` 로 다시 셈(파생 저장 없음). +- DB 에 남는 D 칸 = 등록 칸(`projects`) · 연도 상태 줄(지문 · 확정 시각만) · 업체 줄(조각 번호 · 업체 · 메일 시각 · 연결). +- 옛 길(연도 행 → 노선 · 연도 단위 업체 · 빈 지점 칸 접기)은 DB 실측상 쓰는 프로젝트 0 → 옮김은 지점 옛 꼴(`start` · `end`) 9 개 · 노선 11 개뿐 · 확정 0 · 메일 0 · 연결 0. +- ⑤ 업체 연도 어긋남 실재 — 가이드_예정노선 업체 줄 2 개(id 27 · 28)가 조각과 다른 연도. +- 위성 「한 장짜리」 = 25 장 326.6 MB(D 11 장 133 MB · B 14 장 193 MB) · 조각 = 2 프로젝트 328 장 6.2 MB. 「한 장」의 메타(`vworld_satellite_meta.json`)는 D03 · B04 · B05 지도 틀이라 남김 · 그림만 걷음. +- 새 위험 하나 — storage 가 D 정본을 품음(지금까지 D storage 는 다시 받을 수 있는 것뿐) · Synology 지움 번짐 · 잘못된 정리가 곧 작업 손실. + +## 1. 지금 저장 자리 · 읽고 쓰는 코드 + +### 1-1. DB 칸 + +| 칸 | 꼴 | 쓰는 곳 | 읽는 곳 | +| --- | --- | --- | --- | +| `projects` 등록 칸(이름 · 지역 · `project_year` · `project_year_end` · `design_speed_kph` · `crs_epsg`=5178 고정 · `storage_path`) | 줄 | `common_util_project_kind.py:39-` `create_kind_project`(D01 `D01_PlanRegister_Router.py:35-69`) · `project_year_end` = `D03_PlanAnalysis_Network.py:379-381` | 대시보드 전반 · D04 `D04_PlanConfirm_Repository.py:13-23` · Link `D04_PlanConfirm_Link.py:139-150` | +| `projects.plan_base_json` | `{epsg, points:[{x,y}]}` · 옛 `{epsg, start, end}` | `D02_PlanBase_Router.py:246-251` `_store_base` · `D03_PlanAnalysis_Network.py:390-397` `_freeze_base`(빌 때만) | `D02_PlanBase_Router.py:168-226` `_load` · `base_view` → `load_base`(D03 `Network.py:287` · `:410` · D03 `Router.py:57-67` `_plan_ends`) | +| `plan_networks.network_json` | `{epsg, lines, marks, pieces:[{id,line,from_m,to_m,year}]}` | `Network.py:327-331` | `Network.py:254-269` `_load` · D04 `Repository.py:72-80`(선 이름 차례) | +| `plan_route_pieces` | 조각 한 줄 · `route_json {planned, stations}` · 지문 | `Network.py:332-351`(지우고 다시 넣음) | D04 `Repository.py:60-88` `list_pieces` · Link `Link.py:105-134` `PIECE_JOIN` · D01 `Router.py:87-107` | +| `plan_route_years` | 연도 행 · `route_json`(조각 목록 한 번 더) · `start_x`~`end_y` · `epsg` · `fingerprint` · `confirmed_at` | `Network.py:352-387`(확정 풂 · 빈 연도 = `route_json` NULL 로 남김) · D04 `Repository.py:157-167` `mark_confirmed` | D02 `Router.py:180-185`(빈 지점 접기) · `Network.py:263-268`(옛 노선) · D04 `Repository.py:26-41` · Link `Link.py:142-147` · D01 `Router.py:94` · 대시보드 `B01_Dashboard_Router_Home.py:140-157` `_forest` | +| `plan_route_assignees` | `year`(사본) · `piece_id` · `company_id` · `company_name` · `email` · `notified_at` · `linked_project_id` | D04 `Repository.py:120-154`(INSERT 에 연도) · `:170-175` 메일 시각 · Link `Link.py:160-185` 연결 | 접근 판정 `common_util_auth.py:209-219` · D04 `Router.py:73-93`(같은 업체 열쇠 = 연도 + 조각) · `:301` [확정] 메일 고르기 = `assignee["year"]` · `Network.py:308-326`(지정 조각 지움 막음) · D01 `Router.py:72-127` · 대시보드 `Home.py:144` · `B01_Dashboard_Router_Overview.py:251-262`(연결 「N 년」) | +| 복제 | 위 D 표 넷 | `common_util_project_copy.py:38-40 · 336-345` · `db_management/tools_clone_project.py:11-18` | — | + +### 1-2. storage(D 프로젝트 · `storage/<회사>/<사용자>//`) + +| 자리 | 성격 | 쓰는 곳 | +| --- | --- | --- | +| `D02_PlanBase/` · `D04_PlanConfirm/` | 늘 빔 | 만듦만 `common_util_project_kind.py:21` | +| `D03_PlanAnalysis/임도망도.zip` + `.json` | 정본(사용자 파일) | `D03_PlanAnalysis_ForestRoad.py` | +| `B04_PreProcess/processed/*` · `models_plan/*` · `plan_terrain.json` | 받은 자료 · 지형 | `D03_PlanAnalysis_Terrain.py:225-301` · 겹 `D03_PlanAnalysis_Layers.py` | +| `B04_PreProcess/processed/vworld_satellite.png` + `_meta.json` | 위성 한 장 + 지도 틀 | `Terrain.py:188-221` `_satellite` | +| `B03_FileInput/input/prj/plan.prj` | 좌표계 사본(B04 엔진이 읽음) | `Terrain.py:158-166` | +| `_derived/plan_*` | 파생(최근 2 벌) | `common_util_derived_store.py:64-78` | +| `_derived/plan_tile/Satellite/{z}/{x}_{y}.jpeg` | 위성 조각 · 정리 없음 | `D03_PlanAnalysis_Router.py:354-408` | + +- 프로젝트 정리 `common_util_project_reset.py:23-30` = B04~B09 폴더 통째 지움(B03 올림 때) — 새 파일을 `B04_PreProcess` 에 두면 안 됨 · `D03_PlanAnalysis` 는 밖. + +### 1-3. 화면 · 바깥 길(API 꼴만 봄) + +| 화면 | 길 | 캐시 | +| --- | --- | --- | +| D02 기준 지정 | `D02_PlanBase_UI_Page.ts:277 · 303` GET · PUT `plan/points` | `d02-points`(`A00_Common/b_page_state.ts:204`) | +| D03 노선분석 | `D03_PlanAnalysis_Api.ts:116-123` GET · PUT `plan/network`(응답 `base` · `network` · `derived` · `legacy`) · 지형 `:100-114` | `d03-plan`(`b_page_state.ts:188` · `D03_PlanAnalysis_UI_Page.ts:190-199 · 545`) | +| D04 확정(산림청 · 지정 회사 보기) | `D04_PlanConfirm_UI_Page.ts:110-156 · 309 · 343` summary · assignees · finalize · export | `d04-assignees`(`b_page_state.ts:202`) | +| 대시보드 산림청 홈 | `B01_Dashboard_UI_Home.ts:120-124`(분석 전 · 분석됨 · 확정 · 지정 대기) | — | +| 대시보드 「받은 예정노선」 · [연결](업체) | `B01_Dashboard_UI_AssignedPlans.ts:24` · `B01_Dashboard_UI_PlanLink.ts:32` | — | +| 업체 임도 B03 머리 띠 · 가져오기 | `B03_FileInput_UI_PlanImport.ts:57 · 118 · 143` | — | +| 메일 | `D04_PlanConfirm_Email.py`(본문 = 연도 · 연장) ← `Router.py:276-333` | 안 남음 | +| 내보내기 zip | `D04_PlanConfirm_Router.py:419-444` · `Export.py` | 안 남음 | + +- 서버 Node 묶음 — D 를 부르는 것 없음(`A00_Common/design/**` · `B05_Profile_Corridor_Node.ts` 가 D 를 안 가져옴) · D03 계산은 ① 짝(`D03_PlanAnalysis_Draw.py` ↔ `logic/D03_PlanAnalysis_Draw.ts`)뿐. + +### 1-4. DB 실측(PLAN 11 개 · 지운 것 0) + +| 프로젝트 | 지점 칸 꼴 | 노선 길이 B | 조각 | 연도 줄(빈) | 업체 | 업체 연도 어긋남 | +| --- | --- | --- | --- | --- | --- | --- | +| 가이드_예정노선 `87d47800` | points 4 점 | 1,608 | 5 | 3(1) | 4 | **2**(id 27 = p2 조각 2027 · 줄 2028 · id 28 = p4 조각 2027 · 줄 2029) | +| 검증_sub1_D `a317db7c` | points 2 점 | 1,033 | 4 | 4(1) | 4 | 0 | +| 검증_랩탑메인_D · sub2~sub8_D(8 개) | 옛 `start` · `end` | 1,033 | 4 | 3(0) | 4 | 0 | +| 2026~2030 테스트 지역 간선임도 `4250c7bc` | 옛 `start` · `end` | 2,211 | 1 | 5(4) | 0 | 0 | + +- 표 합 — `plan_networks` 11 줄 13.1 KB · `plan_route_pieces` 42 줄 15.8 KB · `plan_route_years` 36 줄 25.0 KB(빈 6) · `plan_route_assignees` 40 줄. +- 조각 표 = 노선 정본 조각과 전부 같음(어긋남 0) · 노선 없는 연도 행 0 · 조각 없는 업체(`piece_id` NULL) 0 · 확정 0 · 메일 0 · 연결 0 · 연결된 업체 임도 0. +- 좌표계 — 작업 5186(11 개 모두 · 지점 · 노선 · 조각 · 연도 같음) · `projects.crs_epsg` 5178(D 가 안 씀). +- 데스크탑 메인(임시 배포) · 검증자 D 프로젝트 없음 — D 는 전부 랩탑 쪽 검증 · 가이드 · 시험. + +## 2. 새 꼴 설계안 + +### 2-1. 자리 · 이름 + +- `<프로젝트>/D03_PlanAnalysis/plan_network.json` 하나. +- 까닭(자리 규칙) — 값을 낳은 주인 = D03(긋기 · 마크 · 연도) · 452-6 으로 지점 찍기도 D03 로 옴 · 옆에 이미 사용자 정본 `임도망도.zip` · `B04_PreProcess` 밖(B03 올림 정리에 안 지워짐) · `_derived` 아님(다시 셀 수 없음). +- 지점 따로 파일 안 둠 — epsg 가 두 곳 생김(③ 어긋남). +- 프로젝트 id 를 안 넣음 — 복제 도구 UUID 치환 · robocopy 통째 복사에 그대로 맞음. + +### 2-2. 파일 안 꼴 + +```json +{ + "version": 1, + "epsg": 5186, + "points": [{"x": 0.0, "y": 0.0}], + "lines": [{"id": "main", "vertices": [[0.0, 0.0], [10.0, 0.0]], "branch": null}], + "marks": [{"line": "main", "at_m": 5.0}], + "pieces": [{"id": "p1", "line": "main", "from_m": 0.0, "to_m": 5.0, "year": 2027}] +} +``` + +- `epsg` 머리 한 곳(③) · 빈 프로젝트 = `epsg` null · 목록 빔. +- 연도 정의 = 조각의 `year` 뿐 · 따로 연도 목록 없음 → 빈 연도 줄이 생길 자리 없음(②). +- 길이 · 측점 · 조각 좌표(`planned`) · 연도 묶음 · 지문 = 읽을 때 `Network.derive()` · `year_rows()` 로 셈(밀리초 · 몇 KB) · 저장 안 함. +- 지점은 TM x · y 만 · 경위도는 읽을 때(`D02_PlanBase_Router.py:193-197` `_point` 그대로). +- 크기 어림 1.3~2.5 KB(들여쓰기 2 칸이면 2~4 KB). + +### 2-3. DB 에 남길 칸 + +| 칸 | 할 일 | +| --- | --- | +| `projects` 등록 칸 | 그대로 · `project_year_end` = [저장] 때 조각 최대 연도(목록 요약) · `design_speed_kph` 걷음은 452-B 몫 | +| `plan_route_years` | 연도 상태 줄로 줄임 — `year` · `fingerprint` · `confirmed_at` 만 · [저장] 때 있는 연도만 올림 · 없는 연도 줄 지움 · 지문 바뀐 연도만 확정 풂(지금 규칙) | +| `plan_route_assignees` | 조각 번호 + 업체 + 상태(`notified_at` · `linked_project_id`) · `year` 는 읽지 않음(⑤ · 연도 = 파일 조각에서 그때그때) | +| `projects.plan_base_json` · `plan_networks` · `plan_route_pieces` · `plan_route_years` 의 `start_x`~`end_y` · `epsg` · `route_json` | 옮김 1 단계 = 얼림(안 씀) · 2 단계 = 지움(3장) | + +- 대시보드 요약은 DB 연도 상태 줄 + 파일 — 업체 지정 대기(그 연도 조각에 업체 없음)는 조각 → 연도 짝이 파일에만 있어 서버가 프로젝트 파일을 읽어 셈(산림청 D 수십 개 규모 · 파일 몇 KB). + +### 2-4. 서버 한 곳(새 `D03_PlanAnalysis/D03_PlanAnalysis_Store.py` · 150 줄 안) + +- `plan_path(root)` · `load_plan(project_id) → (root, plan)`(파일 · 없으면 옛 DB 칸을 메모리에서 바꿈 · 3장) · `save_plan(root, plan)` = `common_util_json.atomic_write_json`(같은 폴더 임시 파일 · fsync · `replace_with_retry` · 윈도우 공유 위반 재시도) · `plan_units(plan)` = 조각마다 {id · 선 · 선 이름 · 연도 · 길이 · planned · 측점} + 연도마다 {지문 · 조각들}. +- 잠금 = `common_util_save_guard.project_lock(project_id)` 그대로 씀(프로세스 메모리 · ponytail 표시 있음). +- D04 `Repository.list_pieces` · `list_year_routes` 를 이 위에서 같은 꼴로 돌려주면 D04 라우터 · 시험(이 두 함수를 바꿔 끼움)이 거의 그대로. + +### 2-5. 쓰기 차례 · 잠금 + +| 요청 | 잠금 안 차례 | +| --- | --- | +| PUT `plan/network` [저장] · [초기화] | 파일 읽음 → epsg 맞춤(파일 epsg 없으면 새로) → `derive` → 지정 조각 지움 막음(DB 업체) → DB 시작(연도 상태 · 확정 풂 · 사업연도 끝) → 파일 원자 쓰기 → 커밋 · 파일 쓰기 실패면 DB 되돌림 | +| PUT `plan/points`(452-B 전까지) | 파일 읽음 → 지점만 갈아 끼움 → 원자 쓰기 · DB 없음 | +| PUT `plan/assignees` | 파일 조각 id 확인 → DB 업체 줄 | +| POST `plan/finalize` | 파일 → 연도 묶음 → 확정 시각 → 업체마다 조각 연도(파일)로 고름 → 메일 | +| GET 전부 · 지형 받기 | 잠금 없음(원자 바꿔치기라 반쯤 쓴 파일 안 보임) | + +- 커밋 직전 파일을 쓰고 커밋이 깨지는 틈 = 파일 새것 · DB 상태 옛것 → 다음 [저장]이 바로잡음 · [확정] · 내보내기 · 연결은 파일로 다시 세므로 노선은 틀리지 않음(대시보드 수만 잠깐 어긋남). + +### 2-6. 바뀌는 서버 자리(화면 · API 꼴 그대로) + +| 자리 | 바뀜 | +| --- | --- | +| `D02_PlanBase_Router.py:168-270` | 지점 = 파일 · 옛 꼴 · 빈 칸 접기 = 옮김 함수로 | +| `D03_PlanAnalysis_Network.py:218-433` | `_load` · `_store` · `_freeze_base` · `legacy_network` → Store · 조각 · 연도 행 쓰기 걷음 · 응답 `legacy` 는 늘 false 로 남김 | +| `D04_PlanConfirm_Repository.py:26-88` | 연도 · 조각 = 파일 | +| `D04_PlanConfirm_Router.py:73-93 · 127-187 · 221-246 · 300-302` | 같은 업체 열쇠 = 조각 + 업체 · 옛 연도 단위 길 걷음 · 업체 줄 연도 = 파일 조각 연도(GET 응답에도) · [확정] 메일 고르기 = 조각 연도 | +| `D04_PlanConfirm_Link.py:104-150 · 188-199 · 291-306 · 371-398` | SQL 조인 → 업체 줄 + 파일 조각 · 새 임도 사업연도 · 이름 = 조각 연도 · `plan-source` 원본 조인에 `s.deleted_at IS NULL` 더함 | +| `D01_PlanRegister_Router.py:72-127` | 업체 줄(DB) + 프로젝트별 파일 · 확정 = 연도 상태 줄 | +| `B01_Dashboard_Router_Home.py:140-157` · `B01_Dashboard_Router_Overview.py:251-262` | 지정 대기 · 「N 년」 = 파일 조각 연도 | + +## 3. 옮김 + +- 대상 실측 — 11 개 · 지점 옛 꼴 9 · points 2 · 노선 11(전부 `plan_networks` 있음) · 옛 연도 노선만 있는 것 0 · 확정 · 메일 · 연결 0 → 옮길 상태값 없음. +- 읽을 때 옮김 — 파일 없으면 `plan_base_json`(points · `start`/`end` 둘 다) + `network_json` → 새 꼴을 메모리에서 · GET 은 안 씀 · 첫 PUT 때 파일 · 옛 칸은 손대지 않음. +- 가이드_예정노선 업체 줄 id 27 · 28 — 옮긴 뒤 연도가 파일 조각 연도(2027)로 보임 · 2029 연도 줄 사라짐(조각 없음) · D04 표 · 메일이 바른 연도로 바뀜. +- 옛 칸 처리 — 1 단계 남김(얼림) · 2 단계 지움: 11 개 모두 파일 있음 확인(남은 것은 일괄 옮김 한 번) → 옛 칸 덤프 `tmp/backup_452/`(git 밖) → `db_management/023_plan_file.sql`(`plan_networks` · `plan_route_pieces` DROP · `plan_route_years` 여섯 칸 DROP · `projects.plan_base_json` DROP · `plan_route_assignees.year` NULL 허용 또는 DROP) · 복제 도구 D 표 목록 줄임(`common_util_project_copy.py:38-40 · 336-345`) · 시험 573_1 고침. +- 2 단계 때 = 전역 깃 싱크 뒤(데스크탑 임시 배포가 새 코드) · 스키마 바꿈 = 전 창 알림(OWNERS). +- 되돌릴 길 — 1 단계 = 코드 되돌림만(옛 칸 그대로 · 1 단계 뒤 고친 노선은 파일에만 있어 잃음 · 필요하면 파일 → DB 작은 도구) · 2 단계 = 덤프 되살림 + 코드 되돌림. + +## 4. 위성 조각 정리 + +### 4-1. 지금 + +| 무엇 | 자리 | 쓰는 곳 | 실측 | +| --- | --- | --- | --- | +| 조각(GL 바탕) | `_derived/plan_tile/Satellite/{z}/{x}_{y}.jpeg` · 받는 곳 `D03_PlanAnalysis_Router.py:370-408` · 주소 `ui_template/ui_template_gl_map.ts:58-66` | D03 GL(`D03_PlanAnalysis_UI_MapGl.ts:320`) · B04 하단 지도(`B04_PreProcess_UI_MapViewer_Gl.ts:88`) · B05 배수유역(`B05_Profile_UI_Drainage_Gl.ts:162`) — B 프로젝트에도 쌓임 | 검증_sub2_D 208 장 4.2 MB(z14~19) · 검증_sub2(B) 120 장 1.9 MB(z13~19) · 나머지 0 · 한 장 15~21 KB | +| 한 장짜리 그림 | `B04_PreProcess/processed/vworld_satellite.png` | D = 지형 받기 `Terrain.py:188-221` · B = 전처리 `B04_PreProcess_Engine.py:444-470`(위성 · 하이브리드 · 백지도 셋) · 보는 곳 = 옛 캔버스만(D03 `UI_Layers.ts:305-310` · B04 `UI_MapViewer.ts:466 · 506` · B05 `UI_Drainage_Panel.ts:488`) · 미리 받기 `A00_Common/b_asset_cache.ts:480-483` | 25 장 326.6 MB — D 11 장(가이드 23.1 · 시험 21.8 · 검증 9.8 × 9) · B 14 장(13.8 × 14) | +| 한 장의 메타 | `vworld_satellite_meta.json` | **지도 틀** — D03 모든 겹 좌표 틀 · 겹 단추 켬(`UI_Layers.ts:201 · 505-518`) · `vworld-meta` TM 격자(`B04_PreProcess_Router_GIS.py:35-73`) · 도엽 띠 자르기(`B04_PreProcess_Engine_SheetClip.py:59-71`) · GIS 범위(`B04_PreProcess_Engine_GisVector.py:68-80` 백지도 메타 다음) · B05 배수(`B05_Profile_UI_Drainage_Parts.ts:464`) | 1 KB 안 | + +- 숨은 비용 — B [저장] 되돌림 대비가 `_derived` 통째를 임시 폴더로 복사(`common_util_save_guard.py:26-35 · 113-126`) → 조각이 늘수록 B 저장마다 그만큼 복사. + +### 4-2. 규칙안 + +- 「한 장」 걷음 = 그림만 · 메타는 남김 — `B04_PreProcess_Engine_VWorld.py:72-205` 에서 틀 셈(1~3 · 5 차례)을 떼어 「메타만 쓰기」 함수 · D `_satellite` · B 전처리 위성 차례가 그것만 부름 · 하이브리드 · 백지도 그대로. +- 옛 캔버스(GL 못 쓸 때 · D03 끈 단추) = 위성 바탕 없음 · `vworld-map?layer_name=satellite` 는 404 · 미리 받기 줄 걷음. +- 조각 한도 — 프로젝트당 크기 한도(설정 손잡이 `config/config_system_terrain.py` · 제안 30 MB ≈ 1,500~2,000 장 · 지금 한 장짜리 10~23 MB 수준). +- 지우는 때 = 받을 때만(새 조각을 쓸 때) — 프로젝트별 바이트 수를 서버 메모리에 두고 처음 한 번만 폴더를 셈 · 넘으면 수정시각 오래된 것부터 한도 80 % 까지 지움 · 열 때 정리 없음(커지는 길이 받기뿐). +- 읽을 때 수정시각 안 건드림 — 조각 수백 장 `touch` = Synology 동기 일감 · 「오래된 것」= 받은 차례. +- B 도 같은 규칙 — 받는 곳이 하나(`plan/tile`)라 저절로 · 주소 · 자리 이름은 그대로(옮김 = 흔들림만). +- B 저장 되돌림 대비에서 `_derived/plan_tile` 뺌(`common_util_save_guard.py` `_files`). +- 옛 PNG 25 장 지움 = 전역 깃 싱크 뒤 — storage 가 Synology 로 데스크탑과 한 벌 · 임시 배포 옛 코드가 아직 그림을 씀. + +## 5. 프로젝트 지움 + +| 길 | 하는 일 | +| --- | --- | +| 대시보드 [삭제] `DELETE /api/dashboard/projects/{id}`(`B01_Dashboard_Router.py:403-425` · 화면 `B01_Dashboard_UI_Modals.ts:310` · `B01_Dashboard_Api_Fetch.ts:463`) | 시스템 관리자 · 같은 회사 관리자 | +| 소프트(배포 기본) `B01_Dashboard_Repository.py:321-343` | `deleted_at` 만 · DB D 줄 · 폴더 전부 남음(되살릴 수 있음) | +| 하드(`PROJECT_DELETE_HARD_ENABLED` · `config/config_system.py:38` · PC 마다 `.env`) `common_util_project_delete.py:20-89` | DB 먼저(`projects` 한 줄 → D 표 넷 CASCADE · 연결 임도 쪽 `linked_project_id` SET NULL) → 폴더 통째 `rmtree` | +| E01 복사 실패 `E01_StabRegister_Router.py:103` | 하드(E 만) | +| D 전용 지움 | 없음 | + +- ④ 「규칙 하나」 — 설계 내용이 폴더로 오면 하드 = 폴더째 같이 사라짐 · 소프트 = 둘 다 남음 → 새 코드 없음. +- 남는 흠 — 업체 임도 `source_project_id` 는 외래키 없이 남음 · `plan-source`(`D04_PlanConfirm_Link.py:374-384`)가 원본 지움을 안 걸러 소프트 지운 D 의 띠가 남음 → 조인에 `s.deleted_at IS NULL`. +- Synology 주의 — DB 한 벌 + storage 동기 → 랩탑 하드 지움이 데스크탑 폴더에 곧바로 번짐 · 데스크탑 검증 사용자 것도 같은 DB · 하드 지움은 자기 검증 프로젝트만. +- 새 주의 — D 정본이 storage 로 오므로 storage 손 정리 · 동기 충돌본이 곧 작업 손실 · `D03_PlanAnalysis/plan_network.json` 은 지우지 않는 파일로 다룸. + +## 6. 일 나눔 · 위험 · 물음 · 확인 못 함 + +### 6-1. 일 나눔(창 셋 + 끝 단계) + +| 창 | 파일 경계 | 시험 | +| --- | --- | --- | +| 1 저장 자리 | 새 `D03_PlanAnalysis_Store.py` · `D03_PlanAnalysis_Network.py` · `D02_PlanBase_Router.py` — Store 함수 꼴을 첫 커밋으로 올림 | 529_3 · 530_2_plan_analyze · 530_2_plan_router · 새 Store 시험(옛 꼴 셋 옮김 · 원자 쓰기 · 잠금 차례) | +| 2 읽는 쪽(창 1 첫 커밋 뒤) | `D04_PlanConfirm_Repository.py` · `D04_PlanConfirm_Router.py` · `D04_PlanConfirm_Link.py` · `D01_PlanRegister_Router.py` · `B01_Dashboard_Router_Home.py` · `B01_Dashboard_Router_Overview.py` | 563_2 · 531_3 · 531_d04 · 528 · 547_2 | +| 3 위성(따로 돎) | `B04_PreProcess_Engine_VWorld.py` · `B04_PreProcess_Engine.py` · `D03_PlanAnalysis_Terrain.py` · `D03_PlanAnalysis_Router.py`(조각만) · `common_util_save_guard.py` · `config/config_system_terrain.py` · 화면 넷(`D03_PlanAnalysis_UI_Layers.ts` · `B04_PreProcess_UI_MapViewer.ts` · `B05_Profile_UI_Drainage_Panel.ts` · `A00_Common/b_asset_cache.ts`) | 586 · 530_1 · 509_1 · 509_6 · 472_6 | +| 끝(한 창 · 전역 깃 싱크 뒤) | `db_management/023_plan_file.sql` · `common_util_project_copy.py` · `db_management/tools_clone_project.py` · 옛 PNG 지움 | 573_1 | + +- 452-B(등록 기준점 · D02 걷음 · 설계속도)는 창 1 뒤 — `D02_PlanBase_Router.py` · 지점 PUT 이 겹침 · 지점을 D03 [저장] 한 번에 싣는 일은 452-B 몫. +- 화면 확인(D03 저장 · D04 확정 · 대시보드 [연결])은 각 창이 자기 검증 D 로. + +### 6-2. 위험 + +1. DB 한 벌 · storage 동기 · 임시 배포 옛 코드 — 옮긴 D 를 옛 코드가 열면 DB 옛 값을 봄 · 지금 배포 쪽 D 없음 → 전역 깃 싱크 전 데스크탑에서 D 를 안 엶 · 옛 칸 지움 · 옛 PNG 지움은 싱크 뒤. +2. storage 가 D 정본을 품음 — storage 백업 · 동기 충돌본 · 손 정리 규칙이 처음으로 작업 보존에 걸림. +3. 파일 + DB 두 곳 쓰기 틈(2-5) — 노선은 파일로 다시 세서 안전 · 대시보드 수만 잠깐. +4. 잠금 = 프로세스 메모리 — 랩탑 창들 storage 가 같은 폴더(정션)라 두 서버가 같은 D 를 쓰면 못 막음 · OWNERS(창마다 자기 D)로 피함 · 필요하면 MariaDB `GET_LOCK('plan:')`. +5. 대시보드 「분석 전」 수 — 빈 연도 줄이 없어지면 늘 0 · 뜻 바꿈 필요(물음 3). +6. 옛 캔버스 위성 없음 — GL 못 쓰는 PC · D03 끈 단추에서 바탕이 빔. +7. 가이드_예정노선 업체 연도가 바뀌어 보임 — A05 가이드 사진 · 글(`A05_EduDetail/guide/D02/20_쓰인_방법과_근거.md:19` `plan_base_json`)이 낡음 · 가이드 고침은 지시 때. + +### 6-3. 사용자 물음 + +1. 위성 조각 한도 — 프로젝트당 30 MB(≈ 1,500~2,000 장)로 할지. +2. 「한 장짜리」 걷으면 GL 못 쓰는 화면(옛 캔버스 · D03 · B04 · B05 배수)은 위성 바탕 없이 둘지. +3. 대시보드 산림청 「분석 전」 — 「노선 없는 예정노선 프로젝트 수」로 바꿀지. +4. 프로젝트 지움 — 배포에서도 D 를 지금처럼 소프트(폴더 · DB 남김 · 되살림 가능)로 둘지. +5. 등록 기준점(452-6) 자리 — 등록 정보로 보고 DB(`projects`)에 둘지 · 이 파일 `points` 와 별개. + +### 6-4. 확인 못 함 + +- PC 별 하드 지움 설정값 — `.env` 값을 안 봄. +- 데스크탑 storage 실물 · Synology 동기 지연 — 랩탑만 잼. +- storage · DB 백업 유무. +- 옛 캔버스에서 위성 404 일 때 화면 모양 — 실행 안 함. +- D 프로젝트 수십 개 때 대시보드 파일 읽기 시간 — 지금 11 개뿐 · 안 잼. +- 메일 서버 쪽 기록. diff --git a/docs/raw/요구_1025/_분석_452-B_등록기준점_기준지정통합.md b/docs/raw/요구_1025/_분석_452-B_등록기준점_기준지정통합.md new file mode 100644 index 000000000..388a487c8 --- /dev/null +++ b/docs/raw/요구_1025/_분석_452-B_등록기준점_기준지정통합.md @@ -0,0 +1,238 @@ +# 요구 452-B — 등록 설계속도 지움 · 등록 기준점 하나 + 주소 · 기준지정(D02) 걷고 노선분석(D03)으로 통합 · 조사 + +- 근거 = 요구 452 6번(`docs/raw/요구_1025/사용자요구_1025.md` 끝) · `_분석_451` · `_분석_389-A` 1장 · PLAN 579 · 580 · 585 · 같은 폴더 `_분석_452-A_설계내용_폴더.md`. +- 실측 = 코드 읽기 + DB 읽기(SELECT 만 · 2026-10-30). 코드 · git · storage · DB 고침 없음. + +## 0. 한눈에 + +- 설계속도 칸은 개발판 화면에서 이미 빠짐(560-1 · `9ec63ac4f` · 10-27). 남은 것 = 서버가 늘 20 을 박음 · 대시보드 상세가 「설계속도 20 km/h」를 보임 · D04 [연결]이 20 을 B05 씨앗으로 넣음. 데스크탑 임시 배포(`origin/main_desktop_1` · 10-26)에는 옛 칸이 아직 있음. +- 설계속도를 지워도 B 쪽 값은 같음 — 씨앗이 없으면 B05 가 기본값 20 으로 셈(작업임도 · 등급 넷 모두 20). +- 주소 찾기는 이미 있음 — 서버 VWorld `reverse_geocode`(B08 거리이정표가 씀). 다만 프로젝트 주소 아래에만 있어 등록(프로젝트 없음)에서 쓸 공용 길이 하나 필요함. +- 기준점 저장 = DB `projects` 새 칸 셋(경도 · 위도 · 주소). 452-A 와 맞음(등록 정보 = DB · 설계 내용 = `D03_PlanAnalysis/plan_network.json`). +- D03 지점은 452-A 파일의 `points` 에 들어감 → D03 [저장] 한 번에 선과 같이 감 · 되돌리기 · 캐시가 그대로 따라옴. +- D02 가 걸린 자리 = 코드 열여섯 곳 · 가이드 폴더 하나 · 시험 열둘. 단계 행은 PLAN 11 개 모두 NOT_STARTED(D 화면이 단계 상태를 안 씀) → 번호를 바꿔도 잃는 것 없음. +- 큰 걸림 하나 — 지금 D03 긋기는 지점 · 선 끝 · 선 위에서만 시작함(빈 땅 시작 안 됨). D02 를 걷으면 「지점 없이 긋기」를 정해야 함(6장 물음 2). + +## 1. 설계속도 — 쓰이는 곳 · 지우면 + +### 1-1. 쓰이는 곳 + +| 자리 | 하는 일 | 지우면 | +| --- | --- | --- | +| D01 화면 `D01_PlanRegister_UI_Page.ts` | 칸 없음(560-1 에서 걷음 · 머리 주석 4 줄만 언급) | 주석 한 줄 | +| D01 서버 `D01_PlanRegister_Router.py:14-15 · 30 · 54 · 65` | 요청 칸 `design_speed_kph` · `resolve_design_speed(grade_class_of(None))` = 20 → 저장 | 요청 칸 · B05 가져오기 두 줄 · 셈 걷음 · 저장 = 빈 값 | +| 행 만들기 `common_util/common_util_project_kind.py:50 · 67 · 84` | 인자 → `projects.design_speed_kph` | 인자 걷음(E01 은 안 넘김) · SQL 칸은 그대로 두어도 됨 | +| DB `db_management/020_project_groups.sql:14-15` | 칸 `design_speed_kph INT NULL` | **칸은 남김** — DB 가 데스크탑 임시 배포와 한 벌 · 옛 코드 대시보드가 이 칸을 SELECT(`B01_Dashboard_Router_Overview.py:30`) → 칸을 지우면 두 곳 다 500 | +| 대시보드 상세 `B01_Dashboard_UI_ProjectDetail.ts:116 · 202` | 값 있을 때만 「설계속도 N km/h」 | 값이 빈 값이면 저절로 안 보임 → 화면 고칠 곳 없음 | +| 대시보드 목록 `B01_Dashboard_Router_Overview.py:30` · `B01_Dashboard_Api_Projects.ts:15` | 칸 읽기 | 그대로(임도 프로젝트도 씀) | +| D04 [연결] `D04_PlanConfirm_Link.py:142 · 169 · 309-322 · 351 · 361` | 새 임도 = 단계 2 params `options.design_speed_kph` 씨앗 · 임도 행 `COALESCE(design_speed_kph, 예정노선 값)` | 빈 값이면 `seed_design_speed` 가 스스로 건너뜀(314) · COALESCE 도 그대로 → 고치지 않아도 같음 · 걷으면 함수 · SELECT 칸 · COALESCE 걷음(약 −20 줄) | +| B03 자동설계 `B03_FileInput_Service_Chain.py:218-224 · 273` | 단계 2 씨앗을 읽어 B05 노선 풀기에 | B 쪽 · 손대지 않음(씨앗 없으면 None → B05 기본) | +| 글 `ui_template/ui_template_locale_de.ts:92` `DE_Reg_DesignSpeed` | 아무도 안 씀 | 지움 | +| D03 | 쓰지 않음(옛 추천 엔진 걷힘) | — | +| D04 내보내기 · 메일 | 쓰지 않음 | — | +| 가이드 `A05_EduDetail/guide/D01/00_설명서.md:31` · `D01/10_칸_뜻.md:18` · `D04/06_받은_업체_연결.md:16 · 26` · `D04/30_사용자_확정_전_값.md:15` | 「설계속도 받지 않음」 · **`D04/06:16` 「예정노선 설계속도(20 · 30 · 40)가 새 프로젝트 기본값」= 이미 낡음** | 가이드 고침은 지시 때 한 번에 | +| 시험 `test_528_project_groups.py:4 · 116-133` · `test_531_3_plan_link.py:69 · 289-320` | 20 · 40 · 작업임도 20 단언 · 씨앗 시험 셋 | 528 = 「빈 값 저장」 단언으로 · 531_3 씨앗 시험 = D04 씨앗 걷으면 지움 | + +### 1-2. 지우면 B 에 넘길 때 + +- 새 임도 프로젝트 = 임도 종류 `work`(`D04_PlanConfirm_Link.py:300` · 예정노선 `road_type` 빈 값) → B05 설계속도 = `resolve_design_speed("work", None)` = 20(`config/config_system_design.py:571-573` · 등급 넷 모두 20 · 작업임도는 20 만). +- 지금과 결과 같음 · 다른 점 = 연결한 임도 프로젝트 상세에 「설계속도 20 km/h」가 안 붙음(지금 연결된 임도 0 개). +- 옛 PLAN 11 개 = 모두 `design_speed_kph = 20` → 대시보드에 계속 보임. 한 줄 SQL(`UPDATE projects SET design_speed_kph = NULL WHERE project_kind = 'PLAN'`)로 비움 · 전역 깃 싱크 때(임시 배포 옛 D01 이 20 을 다시 박기 때문). + +## 2. 등록에 「기준점 하나 + 주소」 + +### 2-1. 지금 공사지 입력 꼴 + +- D01 = 좁은 카드 하나(`createGeneralLayout({ narrow: true })`) · 칸 셋 = 사업 연도 시작 · 사업 지역(글 · 예 「울진군 금강송면」) · 프로젝트명(이름 조합기 = 「<연도> <사업 지역> 노선 계획」). +- 사업 지역 글이 가는 곳 — 이름 조합기 · 대시보드 · D04 내보내기 shp 「대상지」 칸(`D04_PlanConfirm_Export.py:121 · 141` = **20 바이트로 자름**) · 파일 이름 `대상지_<지역>._<연도>` · 메일 본문 · [연결] 새 임도 지역. +- → 긴 주소(「경상북도 울진군 금강송면 쌍전리 산 12」)를 사업 지역에 넣으면 대상지 칸이 잘리고 파일 이름이 길어짐. **주소는 따로 · 사업 지역은 짧게 유지**가 맞음(물음 4). + +### 2-2. 카카오 지도 넣는 자리 + +- 공용 부품 `ui_template/ui_template_kakao_map.ts` `editMap` 그대로 — 지도 누름 `onClick` · 표지 끌기 `onMove` · 마우스 설정 따름(585-1) · [일반][위성] `setType`(D02 는 `createSegment` 로 단추 · 취향 `aislo:pref:d02.map.type`). +- 주의 — 표지가 없고 `center` 를 안 주면 지도 칸이 숨음(`ui_template_kakao_map.ts:226`) → D02 처럼 `center: () => KOREA_CENTER`(127.8, 36.3) 를 줌. +- 같은 꼴 견본 = B08 소재지 고르기 `B08_Quantity_UI_Milestone_Place.ts`(152 줄 · 주소 찾기 + 지도 누름 + 끌기 + 좌표 → 주소 · 늦게 온 주소 무시 `seq`). 다만 프로젝트 id 에 묶임 · 주소 후보 줄이 날 `el("button")`(부품 규칙 밖). +- 안 — D01 에 지도 칸 하나 + 「주소」 글 한 줄(+ 선택: 주소 찾기 칸 = 이미 있는 `searchAddress` · `GET /api/dashboard/company/address/search`). 카드는 좁은 꼴을 풀거나 지도만 넓게(지도 높이 공용 480 px). +- 공용으로 들어 올릴지 — B08 소재지 고르기를 `ui_template` 부품으로 옮기면 B08 도 고쳐야 함(지금 페이지 밖) → 이번엔 D01 안에서만 · 들어 올림은 뒤로. + +### 2-3. 좌표 → 주소(지오코더) + +| 길 | 있음 | 키 | 비고 | +| --- | --- | --- | --- | +| VWorld `getAddress`(서버) `B01_Dashboard/B01_Dashboard_Map.py:119-143` `reverse_geocode` | 있음 · 시험 `test_244_4` 등 | `VWORLD_API_KEY`(B04 엔진 · 이미 씀) | 도로명 먼저 · 없으면 지번 · 5 s 끊김 · 글 한 줄만 돌려줌(시군구 · 읍면 구조 칸은 버림) | +| 열린 길 `GET /api/projects/{id}/quantity/milestone/reverse`(`B08_Quantity_Router_Milestone.py:457-463`) | 있음 | — | 프로젝트 아래 → 등록에서 못 씀 | +| 주소 → 후보 `GET /api/dashboard/company/address/search` | 있음 | VWorld | 로그인만 | +| 카카오 지오코더(`kakao.maps.services.Geocoder.coord2Address`) | **없음** — SDK 주소에 `libraries=services` 없음(`ui_template_kakao_map.ts:87`) | 카카오 JS 키(도메인 등록) | 넣으면 B08 · D 공용 SDK 가 같이 바뀜 | +| 카카오 REST(Local) | 키는 `.env` 에 있음(B08 길찾기용) · 주소 길 코드 없음 | REST 키 | — | + +- 권고 = VWorld(서버) — 새 길 하나 `GET /api/map/address?lon=&lat=` 를 `common_util/common_util_map_router.py`(카카오 키 길 옆 · `main.py:560` 로그인 보호 이미 걸림)에 · 몸 = `reverse_geocode` 한 줄 부름. +- 임야 주의 — 산은 도로명 주소가 없거나 먼 건물 것이 올 수 있음 → 예정노선은 지번(산 번지) 먼저가 맞을 수 있음 · 실측 필요. +- 사업 지역 채워 주기 — VWorld 응답 `structure`(시도 · 시군구 · 읍면 …)를 쓰면 「울진군 금강송면」 꼴을 자동으로 채울 수 있음 · 지금 함수는 글만 돌려줘 구조 칸을 더 꺼내야 함(응답 꼴 실측 안 함). + +### 2-4. 저장 자리(452-A 와 맞춤) + +- `projects` 새 칸 셋 — `site_lon DOUBLE NULL` · `site_lat DOUBLE NULL` · `site_address VARCHAR(255) NULL`(새 SQL · 번호는 452-A `023_plan_file.sql` 과 겹치지 않게 브레인이 배정). +- 까닭 — 등록 정보 = DB(452-A 2-3 · 6-3 물음 5) · 주소는 찾고 거르는 값 · 경위도는 좌표계 없이 굳음. +- 덧붙이기만이라 DB 한 벌인 임시 배포 옛 코드에 영향 없음 → 아무 때나 올려도 됨. +- 복제 — `common_util_project_copy.py:152` 가 `SELECT *` → 새 칸 저절로 따라감. +- 작업 좌표계 — 지금은 D02 첫 [저장]이 지점 평균 경도로 TM 띠를 정함(`D02_PlanBase_Router.py` `stored_base`). D02 를 걷으면 첫 정함 자리가 없어짐 → 등록 때 기준점 경도로 정함(`common_util_crs.tm_epsg_for_lon` · 5185 · 5186 · 5187). + - 굳히는 자리 안 = 등록 때 452-A 파일 `plan_network.json` 빈 꼴(`epsg` 만)을 써 둠 → 좌표계 한 곳(452-A ③) · 기준점을 뒤에 고쳐도 띠가 안 바뀜. + - 다른 안 = `projects.crs_epsg`(지금 5178 고정 · D 가 안 읽음)에 씀 — 452-A ③(좌표계 여섯 곳)과 겹쳐 그쪽 정함을 따름. +- [등록] 몸 = `{project_name, project_year, region, site: {lon, lat}}` · 서버가 경위도 범위 검사(D02 `LonLat` 120~135 · 30~45 그대로) · 주소는 서버가 한 번 더 찾아 저장(실패 = 빈 값 · 화면 주소 글을 받아 적지 않음). +- 기준점은 등록 필수(산림청만 등록 · 화면 검사 + 서버 422). + +### 2-5. 옛 프로젝트(기준점 없음) + +- DB 실측 — PLAN 11 개(지운 것 0) · 모두 `plan_base_json` 있음(옛 `start`/`end` 9 · `points` 2 · 4 점) · 모두 epsg 5186 · 모두 설계속도 20. +- 처리 안 — 칸 비워 둠(옮김 없음) · 읽을 때 기준점 = 지점 상자 가운데 · 주소 = 「—」 · 범위 규칙은 옛것(지점 + 350 m)만 → 들어올 때 새로 받는 일 없음. +- 기준점을 뒤에 넣는 길이 있으면(물음 5) 옛 프로젝트도 거기서 채움. + +## 3. D02 걷기 + +### 3-1. D02 가 걸린 자리 + +| 묶음 | 자리 | 할 일 | +| --- | --- | --- | +| 길 | `config/config_frontend.ts:125`(`D02_PLAN_BASE`) · `:138-142`(`PLAN_STEP_ROUTES`) | 길 지움 · 단계 = D03 · D04 | +| 단계 틀 | `A00_Common/group_workflow.ts:28-32`(글 셋 · 아이콘 📍🧭✅) | 첫 칸 걷음 | +| [?] [<] [>] | `ui_template/ui_template_help.ts:58-68` | `PLAN_STEP_ROUTES` 를 따름 → 고칠 곳 없음 · D03 이 첫 단계라 [<] 흐림 | +| 단계 행(서버) | `common_util/common_util_workflow_state.py:27`(`PLAN_BASE` · `PLAN_ANALYSIS` · `PLAN_CONFIRM`) | 둘로 | +| 단계 수 | `B01_Dashboard/B01_Dashboard_Router_Overview.py:25`(`PLAN: 3`) | 2 | +| 단계 이름 | `B01_Dashboard/B01_Dashboard_Summary.py:28` | 「기준 지정」 걷음 | +| 대시보드 단계 점 · 막대 · 칸반 · [작업 열기] | `B01_Dashboard_UI_ProjectList_Parts.ts:42-107` · `B01_Dashboard_UI_Home_Cards.ts:68-71` | 단계 수 · 길 목록을 따름 → 고칠 곳 없음 | +| 받은 예정노선 [보기](지정 업체) | `B01_Dashboard_UI_View_Assigned.ts:46` → D02 | D03 으로(D03 이미 보기만 꼴) | +| D01 [등록] 뒤 | `D01_PlanRegister_UI_Page.ts:65` → D02 | D03 으로 → 들어오며 지형 자동 받기(지금 규칙) | +| 폴더 만들기 | `common_util/common_util_project_kind.py:21`(`D02_PlanBase`) | 걷음(늘 빈 폴더) | +| storage 허용 목록 | `config/config_system.py:215` | **남김** — 옛 프로젝트 폴더 · D/E 표지(`common_util_storage.py:24` `KIND_STAGE_MARKERS`)가 이 목록을 씀 | +| 서버 길 | `main.py:79 · 498` · `D02_PlanBase/D02_PlanBase_Router.py`(GET · PUT `plan/points`) | 걷음 · 옛 꼴 읽기(`base_view` · `start`/`end` 감쌈)는 452-A Store 로 옮겨짐 | +| D03 이 D02 를 불러옴 | `D03_PlanAnalysis_Router.py:33 · 57-67` · `D03_PlanAnalysis_Network.py:32 · 287 · 390-397 · 410-427` | 452-A Store 로 바뀜(452-A 2-6) | +| 화면 파일 | `D02_PlanBase/` 넷(UI_Page 314 · Router 143 · Style 48 · draft 길 16) | 폴더째 지움 | +| 캐시 등록 | `A00_Common/b_page_state.ts:204` `d02-points` | 지움 | +| 글 | `ui_template_locale_de.ts:13`(`DE_Step_PlanBase`) · `:121-143`(`D02_*` 열여섯) | 지움 · D03 지점 카드가 쓸 것만 `D03_*` 로 이름 바꿈 | +| 권한 | D02 = 산림청만 고침 · 지정 회사 보기(`D02_PlanBase_Router.py:139`) | D03 이 같은 규칙(`D03_PlanAnalysis_Network.py:407` · 화면 `editable`) → 옮길 것 없음 | +| 가이드 | `A05_EduDetail/guide/D02/`(글 9 · 그림 9 · `_scenes.json` · 864 KB) · 글 속 D02 = `D01/00_설명서.md:27` · `01_새_프로젝트_여는_길.md:26` · `04_입력오류와_등록.md:15` · `10_칸_뜻.md:20` · `D03/00_설명서.md:7 · 9` · `01_지형_받기.md:29` · `02_본선_긋기.md:17` · `08_저장_초기화.md:11` · `20_쓰인_방법과_근거.md:7` | 지시 때 한 번에(D02 폴더 지움 + 고쳐 쓰기 + 다시 찍기) | +| 시험 | `test_280_2_step_nav.py:39-42` + `helper_280_2_step_nav.cjs:121 · 209` · `test_528_project_groups.py:275 · 304` · `test_529_3_plan_points.py`(D02 API 통째) · `test_530_2_plan_router.py:40-46`(`base.load_base` 바꿔 끼움) · `test_553_4_de_parts.py:20-25` · `test_556_2_page_bg.py:13` · `test_560_4_leave_save.py:22-23 · 92 · 107` · `test_401_project_isolation.py:89` · `test_547_1_project_summary.py:24` · `test_548_project_overview.py:41-42 · 75` | 고침 · 529_3 은 D03 지점 시험으로 갈음 | + +### 3-2. 걷는 순서 + +1. D03 이 혼자 섬 — 지점 카드 · 기준점 · 새 범위 규칙(4장) · 옛 지점 읽기(452-A Store). +2. 들어가는 길 — D01 [등록] → D03 · 받은 예정노선 [보기] → D03. +3. 단계 묶음 — 길 · 틀 · 서버 단계 키 · 단계 수 · 이름. +4. 단계 행 번호 SQL(3-3) — 전역 깃 싱크 때. +5. D02 지움 — `main.py` 줄 · D03 의 D02 import 먼저 걷고 → 폴더 지움 → 그 폴더 vite 다시 켬(draft 길 파일 glob · 새 파일 · 지운 파일 뒤 「준비 중」 흠). +6. 글 · 캐시 등록 · 시험. +7. 가이드 — 사용자 지시 때. + +### 3-3. 옛 프로젝트 D02 단계 상태 + +- 실측 — PLAN 11 개 × 3 줄 = 33 줄 모두 `NOT_STARTED`(D 화면이 단계 상태를 한 번도 안 씀 · `D0*` 에 `start_stage` · `complete_stage` 부름 0). +- 화면 영향 — 단계 점은 모두 빈 칸 · 지금 단계 = 0 → 줄 수만 2 로 바꿔도 보이는 차이 없음. +- 그래도 맞춤 — `022_stab_stages_six.sql` 꼴(번호 +100 비켜 둠 → 열쇠로 새 번호): `PLAN_BASE` 줄 지움 · `PLAN_ANALYSIS` 1 → 0 · `PLAN_CONFIRM` 2 → 1. 잃는 상태 없음. +- 시점 — 전역 깃 싱크 때(DB 한 벌 · 임시 배포 옛 코드는 줄 셋 · 새 프로젝트를 만들면 옛 셋 줄을 다시 깖). +- 옛 `D02_PlanBase` 빈 폴더 · 탭에 남은 `d02-points` 캐시 = 그대로 둠(해 없음). + +## 4. D03 으로 옮길 것 + +### 4-1. 옮길 기능 · 자리 + +| D02 기능(지금) | D03 자리 안 | 고칠 파일(지금 줄 수) | +| --- | --- | --- | +| 지점 목록 — 이름 「지점 N」 · 줄 왼 띠 = 지점 색 · 최소 한 줄 · 🗑 · [+ 지점] · 📍 고르기 · 경위도 입력 | 왼쪽 새 카드 「지점」(지형 카드 아래) · [+ 지점] → 다음 지도 누름이 놓음 · 🗑 · 경위도 입력은 `logic/D03_PlanAnalysis_Tm.ts` `lonLatToTm` 로 TM(이미 있음) | 새 `D03_PlanAnalysis_UI_Points.ts`(약 150 줄) · `D03_PlanAnalysis_UI_Page.ts`(562) 에 카드 붙임만 | +| 여섯 색 `pointColor(i)`(`ui_template_palette.ts:41-52`) | 그대로(핀 · 줄 띠 같은 값) | — | +| 지도 표지 끌기 | 핀 겹 `pointLayer` 에 `press` · 끌기 더함(`PlanMapLayer.press` 있음 · `D03_PlanAnalysis_UI_Map.ts:91`) | `D03_PlanAnalysis_UI_DrawPaint.ts:140-`(296) | +| 지도 누름 = 놓기 | 「지점 놓기」 걸음 — 긋기와 같은 누름 자리에서 갈래 | `D03_PlanAnalysis_UI_Draw.ts`(497) 또는 Points 파일 | +| 저장 = `PUT plan/points` 따로 | D03 [저장] 한 번 — 몸에 `points: [[x, y]]` · 서버 `Network` 모델에 `points` 칸(최대 40) · 452-A 파일 `points` 로 | `D03_PlanAnalysis_Network.py:67-71`(433) · `logic/D03_PlanAnalysis_Plan.ts:31-34` `PlanNetwork`(616) · 캐시 `DRAFT_VERSION` 2 → 3(`UI_Page.ts:73` · 옛 캐시는 버림) | +| 되돌리기 | 지점 고침도 `commit` 한 번 = 한 걸음(네트워크 안이라 저절로) | — | +| 떠남 물음 | D03 `dirty` 가 네트워크 전체를 비교 → 저절로 | — | +| 산림청만 고침 | D03 `editable` 그대로 | — | + +- 지점이 지문에 안 들어감 — 조각 · 연도 지문은 선에서만 셈(`Network.py:332-387`) → 지점을 옮겨도 [확정]이 안 풀림(지금과 같음). + +### 4-2. 지점에 놓인 꺾임점 잠금 + +- 지금 — 지점 자리 꺾임점은 못 끎(`D03_PlanAnalysis_UI_Edit.ts:249-253` 「지점 자리 점은 1단계(기준 지정)에서 옮깁니다.」) · 긋기 붙음(`UI_Draw.ts:217-223`) · 지점 누름 = 새 본선 또는 그 점의 갈래(`UI_Draw.ts:347-360`) · 지점 위 선 끝은 이어 긋기 대상 아님(`UI_Draw.ts:328-336`). +- 안 ⓐ(권고) — 잠금 유지 · 핀을 끌면 그 자리 꺾임점이 같이 옮겨짐(같은 점 찾기 한 바퀴 · 약 15 줄) · 알림 글 = 「지점 핀을 끌어 옮깁니다」. +- 안 ⓑ — 잠금 풂 · 핀과 선 따로 · 꺾임점을 끌면 지점에서 떨어짐. +- 지점을 지우면 그 자리 꺾임점은 보통 점이 됨(잠금 풀림) · 뒤 지점 번호 · 색이 한 칸씩 당겨짐(D02 와 같음). + +### 4-3. 기준점 표시 + +- 기준점 = 등록 값(D03 에서 안 고침 · 물음 5) · 지도에 다른 꼴 표지 하나(회색 십자 · 이름 「기준점」) · 붙음 · 잠금 없음 · 범위 중심 몫만. +- 처음 맞춤 — 지금 `map.update({ fit: [...points, ...꺾임점] })`(`UI_Page.ts:548`) · 점 하나면 너무 당겨짐 → 맞춤 = 기준점 ± 반경 상자 ∪ 지점 · 선. +- 빈 화면 글 — `UI_Page.ts:539` 「지점이 비었습니다 — 1단계(기준 지정)에서 정하세요.」에서 return → 새 프로젝트는 늘 기준점이 있어 이 글 걷음 · 기준점도 지점도 없을 때만 「기준점이 없습니다」. + +### 4-4. 자동 받기 범위 — 지금 · 새 규칙 + +- 지금 — 범위 = 지점 상자 + 여유 350 m(300~5000 · `D03_PlanAnalysis_Terrain.py:49-50 · 74-89`) ∪ 받은 범위(줄지 않음) · 들어올 때 못 덮으면 바로 받기(`UI_Page.ts:553-558` · 산림청만) · 지점 · 선이 받은 범위 밖이면 글 + [범위 밖 더 받기](`UI_Page.ts:153-164 · 244-276`) · 받은 범위 테두리는 받기 창(카카오) 안에만 보임 · 본 지도엔 없음. +- 서버 범위 입력 — `_plan_ends`(`D03_PlanAnalysis_Router.py:57-67`)가 D02 지점을 읽고 없으면 400 · 지도 겹 길 열둘도 이것을 거침(`_layer_root` `:168-173`). +- 새 규칙 안: + - 범위 = (기준점 ± R) ∪ (지점 · 그은 꺾임점 + 여유) ∪ 받은 범위 · 기준점 없는 옛 프로젝트 = R 칸 건너뜀. + - R = 새 설정 값 하나(`Terrain.py` `DEFAULT_MARGIN_M` 옆 · 사용자 확정 값) · `wanted_box` 에 상자 하나 더함(약 10 줄) · `_plan_ends` = 기준점 + 지점(없어도 400 아님). + - 들어올 때 = 지금 그대로(못 덮으면 바로 받기) → [등록] 직후 D03 이 열리며 지형 받기 시작. + - 지점 더함 → 받은 범위 밖이면 핀을 빈 꼴로 · 본 지도에 받은 범위 점선 테두리(새 겹 · `UI_DrawPaint.ts`) · [범위 밖 더 받기]에 지점도 넣음(지금은 꺾임점만 `allVertices()`). + - 자동으로 더 받을지(물음 8) — 권고 = 단추만(받기는 수십 초 · 저장소 커짐 · 누를 때만). + +### 4-5. 받는 크기 · 시간 어림 + +- 단가(검증_sub1_D 실측 · 상자 1.78 × 1.70 km = 3.0 km² · 도엽 2 매) — 지형면 7.2 MB/km² · 지적 1.4 MB/km² · 도엽 한 매당 약 12 MB(zip 1.2 + 병합 4.0 + 표시 사본 2.4 + 위성 4.9). +- 도엽(1:5,000) 한 매 = 0.025° × 0.025° ≈ 2.8 × 2.2 km. +- 2 m 격자 칸 수 = 넓이 km² × 25 만. + +| R | 상자 | 넓이 | 도엽(보통 · 많으면) | 지형 칸 | 크기 어림 | 시간 어림 | +| --- | --- | --- | --- | --- | --- | --- | +| 500 m | 1 × 1 km | 1 km² | 2 · 4 | 25 만 | 약 35 MB | 20~30 s | +| 1,000 m | 2 × 2 km | 4 km² | 3 · 4 | 100 만 | 약 70~85 MB | 40~70 s | +| 1,500 m | 3 × 3 km | 9 km² | 5 · 9 | 225 만 | 약 140~190 MB | 약 2 분 | +| 2,000 m | 4 × 4 km | 16 km² | 7 · 9 | 400 만 | 약 230~250 MB | 3 분 넘음 | + +- 시간 근거(실측 셋 · 어림) — 검증_sub2_D 1.1 × 1.3 km 28 s(지적 같이 · `2026-10-28_plan_568-569.md`) · 가이드_예정노선 도엽 12 매 25 s(도엽 이미 받음 · `2026-10-26_plan_538-542.md`) · 검증_sub3 약 9.5 km² 새 도엽 12 매 123 s(옛 코드 · 연도 지형 두 벌 · `2026-10-25_plan_528-535.md`). +- 452-A 위성 정리(한 장짜리 그림 걷음)가 들어오면 도엽 한 매당 약 5 MB 줄어듦. +- 받은 범위는 줄지 않음(451 3장 8) — 기준점을 뒤에 옮기면 옛 범위 ∪ 새 범위로 커지기만. + +## 5. 일 나눔 · 452-A 겹침 + +### 5-1. 창 둘 + +| 창 | 일 | 파일 경계 | 시험 | +| --- | --- | --- | --- | +| B1 등록(452-A 와 동시 가능) | 설계속도 걷음 · 기준점 + 주소 · 주소 길 · 새 칸 SQL · 좌표계 굳힘(452-A 파일 빈 꼴 또는 칸) | `D01_PlanRegister/*` · `common_util/common_util_map_router.py` · `common_util/common_util_project_kind.py`(인자) · `D04_PlanConfirm/D04_PlanConfirm_Link.py`(씨앗 부분만) · 새 SQL 한 장 · `ui_template_locale_de.ts`(`DE_Reg_*`) | 528 · 531_3 · 557_2 · 새 주소 길 시험(VWorld 가짜) | +| B2 통합(452-A 창 1 Store 뒤) | D03 지점 카드 · 핀 끌기 · 잠금 · 기준점 표지 · 새 범위 규칙 · D02 걷음 · 단계 묶음 · 단계 행 SQL | `D03_PlanAnalysis/*`(Page · 새 UI_Points · UI_Edit · UI_Draw · UI_DrawPaint · logic/Plan · Network · Router · Terrain) · `D02_PlanBase/`(지움) · `config/config_frontend.ts` · `A00_Common/group_workflow.ts` · `A00_Common/b_page_state.ts` · `common_util/common_util_workflow_state.py` · `common_util/common_util_project_kind.py:21` · `B01_Dashboard_Router_Overview.py:25` · `B01_Dashboard_Summary.py:28` · `B01_Dashboard_UI_View_Assigned.ts:46` · `main.py` · `ui_template_locale_de.ts`(`D02_*` · `DE_Step_PlanBase`) | 280_2 · 528 · 529_3(갈음) · 530_2 · 553_4 · 556_2 · 560_4 · 401 · 547_1 · 548 · 585_1 · 585_2 | + +- B2 는 화면 · 서버가 한 덩어리(지점 꼴 = 서버 모델 · 화면 꼴 · 캐시 판) → 한 창(Opus) · 나누면 이음 꼴부터 정해 첫 커밋. +- 가이드(D01 · D02 지움 · D03 · D04) = 사용자 지시 때 한 창. + +### 5-2. 452-A 와 겹치는 곳 + +| 자리 | 452-A | 452-B | 차례 | +| --- | --- | --- | --- | +| `D02_PlanBase_Router.py` | 지점 읽기 · 쓰기를 파일로(창 1) | 파일째 지움 · 옛 꼴 읽기는 Store 로 | A 창 1 → B2 | +| `D03_PlanAnalysis_Network.py` | `_load` · `_store` · `_freeze_base` → Store | `points` 칸 · 기준점 응답 | A 창 1 → B2 | +| 지점 PUT `plan/points` | 452-B 전까지 파일로 살림 | 걷음 · D03 [저장]에 실음 | A 창 1 → B2 | +| `plan_network.json` 꼴 | `points` · `epsg` 칸 이미 있음 | 그대로 씀 · 등록 때 빈 꼴(`epsg`) 쓰기 안 | 꼴 = A 가 정함 | +| `D04_PlanConfirm_Link.py` | 조인 → 파일 조각(창 2) | 설계속도 씨앗 걷음(한 덩어리 · 다른 줄) | 같은 파일 · 다른 줄 — B1 이 먼저면 A 창 2 가 받음 | +| `D01_PlanRegister_Router.py` | 받은 예정노선 목록 = 파일(창 2) | 등록 요청 꼴(같은 파일 위쪽) | 같은 파일 · 다른 함수 | +| `common_util_project_kind.py` | — | B1 인자 · B2 폴더 목록 | B1 · B2 같은 파일 · 다른 줄 | +| DB SQL 번호 | `023_plan_file.sql`(끝 단계) | 새 칸 한 장 · 단계 행 한 장 | 브레인이 번호 미리 배정 | +| 좌표계 한 곳(③) | 파일 머리 `epsg` · `crs_epsg` 정리 | 등록 때 기준점 띠로 굳힘 | A 정함을 따름 | +| 시험 529_3 · 530_2 · 573_1 | 고침 | 고침 · 갈음 | A 먼저 | + +## 6. 사용자 물음 + +1. 기준점 주변 몇 m 를 받을지 — 4-5 표 · 권고 1,000 m(2 × 2 km · 도엽 3~4 매 · 약 80 MB · 1 분 안팎) · 넓은 노선은 지점을 더해 넓힘. +2. 지점 없이 긋기 — 지금은 지점 · 선 끝 · 선 위에서만 긋기 시작(`UI_Draw.ts:374` 「지점 · 선 끝 · 선 위를 눌러 시작합니다.」). 안 ⓐ 빈 땅 누름도 새 본선(지점 없어도 됨 · 권고) · ⓑ 지점을 하나 이상 놓아야 긋기(지금 규칙). +3. 기준점을 긋기 붙는 점으로도 쓸지 — 권고 = 아니오(대략 위치 · 범위 중심만 · 다른 꼴 표지). +4. 사업 지역 · 주소 — 권고 = 주소는 따로 저장 · 사업 지역은 주소에서 「시군구 읍면」을 채워 주되 손으로 고칠 수 있음(내보내기 「대상지」 칸 20 바이트 · 파일 이름). +5. 등록 뒤 기준점 고치는 자리 — 대시보드 프로젝트 정보 고침 창에 같은 지도(산림청만) · D03 에서 끌기 · 고침 없음 중 하나 · 권고 = 정보 고침 창. +6. 지점 핀을 끌면 그 자리 꺾임점도 같이 옮길지(권고) · 따로 둘지. +7. D03 [초기화] 때 지점도 지울지 — 권고 = 선만 지우고 지점은 둠. +8. 지점을 받은 범위 밖에 놓으면 — 단추 [범위 밖 더 받기]만(권고) · [저장] 때 자동 받기. +9. 주소 출처 — VWorld(서버 · B08 과 같음 · 권고) · 카카오 지오코더(지도 부품 SDK 를 바꿈). + +## 7. 확인 못 함 + +- VWorld 좌표 → 주소가 임야(산 번지)에서 주는 글 · 구조 칸(시군구 · 읍면) 꼴 — 실행 안 함. +- R 별 받기 시간 · 메모리 — 옛 실측 셋에서 어림 · 4 km² 넘는 상자는 안 잼. +- 카카오 JS 키 도메인에 등록 화면이 쓰일 주소가 다 들어 있는지(D02 가 뜨는 주소면 같음 · 임시 배포 주소 미확인). +- 데스크탑 임시 배포 D01 실제 판 — `origin/main_desktop_1` 으로만 봄(데스크탑 폴더 실물 못 봄). +- 452-A 의 좌표계 · 파일 빈 꼴 정함 — 아직 계획 전. +- D03 GL 바탕(586)에서 핀 끌기 누름이 캔버스 겹까지 오는지 — 코드상 `press` 길이 있음 · 실행 확인 안 함. diff --git a/docs/raw/요구_1025/요구서_452_예정노선_저장자리_등록기준점.md b/docs/raw/요구_1025/요구서_452_예정노선_저장자리_등록기준점.md new file mode 100644 index 000000000..8fc9a247d --- /dev/null +++ b/docs/raw/요구_1025/요구서_452_예정노선_저장자리_등록기준점.md @@ -0,0 +1,44 @@ +# 요구서 452 — 예정노선 설계 내용 = 프로젝트 폴더 · 등록 기준점 하나 · 기준지정 페이지 걷고 노선분석으로 통합 + +원문 = `사용자요구_1025.md` 요구 451 · 452 · 근거 = `_분석_451_예정노선_영구저장.md` · `_분석_452-A_설계내용_폴더.md` · `_분석_452-B_등록기준점_기준지정통합.md`. + +## 1. 사용자 확정 + +- DB = 여러 프로젝트를 찾고 거르는 것만(등록 정보 · 업체 지정 · 상태 · 확정 · 메일 시각 · 목록 요약) · 프로젝트 폴더 = 설계 내용. +- ① 위성 조각 = 폴더 저장본 한 벌 · 크기 한도 · 오래된 것부터 지움 · 「한 장짜리」 걷음 · B 도 ② 조각 · 연도 정의 = 노선 원본과 한 파일 ③ 좌표계 = 파일 머리 한 곳 ④ 프로젝트 지움 = 폴더 + DB 등록 · 업체 줄 ⑤ 업체 지정 = 조각 번호만 · 연도는 파일에서. +- 등록: 설계속도 지움 · 카카오 지도로 기준점 하나 + 주소 · 기준점 주변 자료를 노선분석이 받음 · D02 기준지정 페이지 걷음 · 지점 마킹(목록 · 여섯 색 · 핀)은 D03 으로. + +## 2. 조사 결과 (줄임) + +- 설계 내용 한 파일 = `D03_PlanAnalysis/plan_network.json`(지점 · 선 · 조각 · 연도 · 좌표계 · 길이 · 측점 · 조각 좌표는 열 때 서버가 셈) · DB 에는 등록 칸 · 연도별 확정 상태 · 업체 줄(조각 번호 · 업체 · 메일 시각 · 연결)만 · 화면은 DB 를 직접 안 봐 화면 고칠 곳 거의 없음. +- 옮길 양 = 예정노선 11 개(검증 · 가이드 · 시험) · 확정 · 메일 · 연결 0 · 옛 꼴 지점 9 개만 변환 · 가이드_예정노선 업체 줄 2 개가 조각과 다른 연도를 가리킴(⑤ 실재 · 옮기면 바로잡힘). +- 위성 「한 장짜리」 25 장 326.6 MB · 조각 6.2 MB · 그림만 걷고 메타(좌표 틀)는 남김 · 덤 = 임도설계 [저장] 때마다 위성 조각 폴더까지 통째 복사 → 빼는 안. +- 설계속도 = 개발판 등록 화면은 10-27 에 이미 빠짐 · 서버가 늘 20 저장 · 대시보드 상세 표시 · D04 연결 때 20 넘김 → 지워도 B05 기본 20 이라 업체 결과 같음. +- 기준점 + 주소 = VWorld 좌표 → 주소 기능 있음 · DB 프로젝트 칸 셋(경도 · 위도 · 주소) · 옛 11 개는 지점 가운데를 기준점으로. +- D02 걷기 = 코드 16 · 가이드 폴더 1 · 시험 12 · 단계 상태 모두 「시작 전」 · 걷는 순서 있음. +- D03 = 지금은 지점이 없으면 긋기 시작 못 함 → 규칙 정해야 함 · 기준점 주변 1,000 m ≈ 2 × 2 km · 약 80 MB · 1 분 안팎(어림). +- 새 위험 = storage 에 사용자 정본이 들어감 · Synology 로 지움이 데스크탑에 번짐 · 옛 DB 칸 · 옛 위성 그림 지우기는 전역 깃 싱크 뒤에만. + +## 3. 사용자 결정 (괄호 = 권함) + +1. 위성 조각 한도 — 프로젝트당 (30 MB ≈ 1,500~2,000 장). +2. 「한 장짜리」 걷은 뒤 그래픽 가속 못 쓰는 화면(옛 캔버스)의 위성 바탕 — (없이 둠 · 알림). +3. 대시보드 산림청 「분석 전」 — (「노선 없는 예정노선 프로젝트 수」). +4. 프로젝트 지움 — (지금처럼 소프트 · 폴더 · DB 남김 · 되살림 가능). +5. 기준점 주변 받는 범위 — (1,000 m · 넓은 노선은 지점을 더해 넓힘). +6. 지점 없이 긋기 — (빈 땅 누름도 새 본선 · 지점 없어도 됨). +7. 기준점을 긋기 붙는 점으로도 쓸지 — (아니오 · 대략 위치 · 범위 중심만). +8. 주소 · 사업 지역 — (주소 따로 저장 · 사업 지역은 주소에서 「시군구 읍면」 채우되 손으로 고침). +9. 등록 뒤 기준점 고칠 자리 — (대시보드 프로젝트 정보 고침 창에 같은 지도). +10. 지점 핀을 끌면 그 자리 꺾임점도 — (같이 옮김). +11. D03 [초기화] 때 지점 — (선만 지우고 지점은 둠). +12. 받은 범위 밖에 지점 — ([범위 밖 더 받기] 단추). +13. 주소 출처 — (VWorld · 서버 · B08 과 같음). + +## 4. 배정안 (승인 뒤) + +- 590-1 저장 자리(서버 · plan_network.json · 옮김 · DB 줄임 · ⑤) — 창 하나 Opus. +- 590-2 위성 정리(한도 · 한 장짜리 걷음 · B 저장 복사 뺌) — 창 하나 Opus · 590-1 과 동시. +- 591-1 등록(설계속도 지움 · 기준점 + 주소 · 대시보드 고침 창) — 창 하나 · 590-1 과 동시. +- 591-2 D02 걷기 · D03 통합(지점 · 핀 · 긋기 규칙 · 받는 범위) — 590-1 저장 모듈 뒤. +- 590-3 옛 DB 칸 · 옛 위성 그림 지우기 = 전역 깃 싱크 뒤 한 번.