- `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>
8.3 KiB
8.3 KiB
이관 계획서 (Archived Plan)
- 이관 일자: 2026-07-18
- 대상 작업: B04 전처리를 old 버전 방식으로 정렬 (2026-07-18)
- 상태: 완료 및 검증 완료로 활성 계획에서 이관
배경
old 버전(0_old/main.py + 0_old/utils/)은 업로드 직후 구조화→필터 4종→모델 15종→등고선 캐시→VWorld/GIS를 전부 사전 처리하고 문제없이 동작했다. 본 프로그램(B04)은 계산 코어를 그대로 포팅했으나 old의 3가지 장치가 빠졌고 등고선 캐시 간격이 어긋나 있었다:
- 지면 마스크 영구 저장(
mask_*.npy) 없음 → 매 분석·미리보기마다 CSF/PMF 재계산 structured.npz존재 시 스킵 로직 없음 → 구조화 무조건 재실행- 엔진 계층 로그 0건 + 백그라운드 트리거에 진행률 콜백 미전달 → 침묵 상태로 수 분 소요
- 등고선 사전 캐시 5.0m vs 프론트 요청 1.0m 불일치(작업 트리에서 1.0m로 수정됨) + on-demand 재계산이
adaptive_contour_grid_resolution(old에 없음)을 사용
방향: 최대한 old 방식을 따른다. old에 없는 신규 장치는 삭제한다. 문제가 생기면 그때 변경한다.
저장 위치 매핑 (old → 본 프로그램)
old (instance/{proj}/) |
본 프로그램 ({project_root}/B04_wf1_Surface/) |
|---|---|
structured.npz |
processed/structured.npz (기존 동일) |
mask_{filter}.npy |
processed/mask_{filter}.npy (신규 저장) |
terrain_models/* (모델·manifest·등고선) |
models/* (기존 동일) |
vworld_*, GIS geojson |
processed/* (기존 동일) |
완료 구현 체크리스트
A. 마스크 영구 저장·재사용 — B04_wf1_Surface_Engine.py
- A-1.
run_surface_analysis: 필터별processed/mask_{filter}.npy존재+길이 일치 시np.load(mmap_mode="r")재사용, 없으면 계산 후np.save.force=True면 재계산 - A-2.
cache_ground_points: mask 미전달 시build_ground_masks대신 저장된mask_{filter}.npy우선 로드 (없을 때만 필터 실행 후 저장)
B. 구조화 스킵 + 입력 세대 검증 — B04_wf1_Surface_Engine.py
- B-1.
structured.npz존재 &&force=False면structurize_las스킵 (oldupload_files스킵 로직과 동일 원리) - B-2. 입력 LAS 정체성(파일명+크기+mtime)을 structured.npz(또는 sidecar json)에 기록, 불일치 시 구조화·마스크·모델 캐시를 force 취급으로 무효화 — old는 업로드마다 새 프로젝트 폴더라 이 문제가 없었으나 본 프로그램은 같은 폴더를 재사용하므로 필수
C. 로깅·진행률 복원 (old의 print 진행 표시를 logger로 대체)
- C-1.
run_surface_analysis: 단계별 시작/완료logger.info+ 소요시간(구조화/필터별/모델빌드/VWorld/GIS/총계) - C-2. VWorld·GIS 다운로드
except: pass→logger.warning으로 실패 사유 기록 (old는 print로 출력했음) - C-3.
build_all_terrain_models호출 시 progress reporter 연결 (_report래핑, 70~90% 구간 배분) - C-4. B03
trigger_wf1_analysis_and_email:on_progress콜백 전달 →write_surface_progress로 progress.json 갱신 (업로드 자동 전처리도 진행률 노출)
D. 등고선 old 정합 — B04_wf1_Surface_Engine_Contour.py, B04_wf1_Surface_Router_Contour.py, B04_wf1_Surface_Engine_Pipeline.py
- D-1.
adaptive_contour_grid_resolution삭제, on-demand 재계산도 old처럼 config 고정 격자(SURFACE_CONTOUR_GRID_RESOLUTION_M=1.0) 사용 - D-2. NURBS 스플라인
s=0→ old 공식s=len(control_x)*len(control_y)*0.01복귀 (추출 로직을 old와 동일화;CONTOUR_EXTRACTOR_VERSION=4는 유지해 기존 캐시 전면 재생성) - D-3. Pipeline 캐시 재사용 분기: dtm/tin은
_smooth_등고선 파일 존재도 검사해 누락 시 재생성 (프론트 기본값이 스무딩 ON이므로) - D-4. 사전 캐시 간격 1.0m 유지 (작업 트리 수정분 유지 — old config와 동일)
- D-5. 모델 (재)빌드 직전 해당 stem의
contour_{filter}_{method}*.json전부 삭제 + 라우터 캐시 검사에 "모델 npz mtime > 등고선 캐시 mtime → 재계산" 추가 — 같은 경로를 세대 구분 없이 재사용하므로 구세대 등고선 잔존 방지 (외부 검토 지적 채택) - D-6.
SURFACE_MODEL_PRECOMPUTE순서를dtm우선으로 변경 — TIN 등고선 사전 캐시가dtm_{filter}.npzfootprint를 참조하는데 tin이 먼저 빌드되면 footprint 미적용으로 캐시됨. old도 tin 우선이라 동일 결함이 있었으나 저비용 개선이므로 채택 (외부 검토 지적 채택)
E. 이상한 것 삭제·정리
- E-1.
run_surface_analysis의 3중.prjglob(**/*.prj재귀 포함) 제거 → B03 입력 폴더에서 명시적 1회 탐색 - E-2. 재분석 시 해당 프로젝트의
surface_models기존 행 삭제 후 INSERT — 실측 결과 한 프로젝트에 121행 누적, 전부 동일 파일 경로를 가리키며 디스크에는 일부만 존재(중단된 분석). 화면은 이 목록의 첫 매치를 선택하므로 "파일 없는 모델 선택 → 프리뷰/등고선 404"가 미반영 증상의 1차 원인 중 하나 (외부 검토 실측 채택)
F. config 파라미터 old 값 복귀 — config/config_system.py (변경 시 config_signature 변경 → 모델 캐시 전면 재빌드됨)
- F-1.
SURFACE_IMPLICIT_MAX_POINTS_PER_TILE20000→10000,SURFACE_IMPLICIT_SMOOTHING0.5→0.1 - F-2.
SURFACE_TIN_MAX_INPUT_POINTS200000→500000,SURFACE_MAX_PREVIEW_VERTICES120000→500000 - F-3.
SURFACE_MESHFREE_MAX_MODEL_POINTS300000→500000,SURFACE_MESHFREE_POINT_RADIUS_M0.5→0.15
G. 프론트 경합 보완 (소규모) — B04_wf1_Surface_UI_TerrainViewer.ts
- G-1. GLTF/PLY 로더 콜백에 요청 세대 토큰 가드 추가 — 선택 변경 후 늦게 도착한 이전 메쉬가 scene에 겹쳐 남는 문제 차단 (등고선 fetch에는 이미 가드 있음)
H. 코딩 후 실측 테스트에서 발견·해결한 추가 문제 (2026-07-18 오후)
- H-1. TIN/meshfree 등고선 수 분 소요·행(Hang)의 진짜 원인 = scipy 버전: venv의 scipy 1.13.1에서
scipy.spatial.Delaunay.transform(무게중심 변환 지연 계산)이 97만 심플렉스 기준 114~280초 소요 (실측). old 환경은 scipy 1.18.0(0_old/requirements.txt, UTF-16 인코딩 주의)이라 빨랐음. old 데이터를 현재 venv에 넣어도 동일하게 느린 것으로 교차 검증 완료 → 데이터·코드 문제 아님. 조치: venv scipy를 1.16.3(현재 numpy 1.26.4와 호환되는 최신)으로 업그레이드,requirements.txt핀 1.13.1→1.16.3 갱신. transform 15.8초로 단축, TIN 등고선 1개당 25~27초. 완전한 old 동등(scipy 1.18)을 위해서는 numpy 2.x 마이그레이션 필요 → Backlog 참조 - H-2. 진단 과정에서
_grid_axes를 float64로 바꿨다가 오진으로 판명되어 old와 동일한 float32로 원복 (H-1이 진짜 원인; 최종 작업 트리에서 이 함수는 무변경) - H-3. 분석 중 서버 프로세스 침묵 소멸의 원인 = uvicorn 자동 리로드:
.env의DEBUG=True→main.py:268의reload=DEBUG활성화 → 분석 도중 .py 파일이 저장되면 백그라운드 분석 스레드째 재시작(2회 재현 확인). 조치:.envDEBUG=False로 변경 + 사유 주석 추가 - H-4. 전처리 전체 재개 실측 검증 완료 (프로젝트
storage/1/3/acb9…, cloud_merged.las 606만 지면점): 15개 모델 + 등고선 캐시 21개 + VWorld 3종 + GIS 벡터 6종 전부 생성, manifestcompleted, 실패 0, 총 433초 (구조화 스킵·마스크 3종 캐시 재사용 각 0.03초·dtm 1종 캐시 재사용 상태 기준. 전체 신규 계산 시 구조화 ~2분 추가 예상). A·B·C·D 캐시/스킵/로그/진행률 로직 동작 확인됨
완료된 백로그 (Completed Backlog)
- TIN coverage 마스크 rasterio.features.rasterize 대체 검토 (2026-07-18):
B04_wf1_Surface_Engine_Contour.py의_tin_face_coverage_mask함수 내에서 shapelyunion_all과intersects_xy연산의 오버헤드를 줄이기 위해 rasterio의rasterize방식으로 전환 완료. (Delaunay transform 병목 해소와 병행해 성능 체감 효과 확보)