Files
Aislo/docs/raw/plans/2026-07-18_plan_crs_normalization.md
eomsangdonandClaude Opus 5 eb30b774f8 chore(docs): docs 폴더 git 추적 전환 · PLAN·OWNERS 최상위 이관
- `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>
2026-09-09 18:19:07 +09:00

4.5 KiB

Plan History: B03 업로드 CRS 정상화

  • 완료 일자: 2026-07-18
  • 수행 주체: 개발 전문 AI
  • 검증 결과: 합격 (PASS)

B03 업로드 CRS 정상화

목표

  • 복합 CRS 전체의 to_epsg() == None을 수평 CRS 판별 실패로 오인하지 않는다.
  • GeoTIFF·PRJ·LAS에서 수평 CRS와 수직 CRS를 분리해 동일한 메타데이터 구조로 저장한다.
  • 기존 DB 연동 필드인 epsg에는 지도 좌표 변환에 사용할 수평 EPSG를 유지한다.
  • KNGeoid24처럼 공식 EPSG가 없는 수직 CRS는 오류나 임의의 EPSG로 치환하지 않고 사용자 정의 수직 CRS로 기록한다.
  • 실제로 알 수 없는 수평 CRS는 추측하지 않고 상태값으로 명확히 남긴다.

구현 원칙

  • GeoTIFF는 파일 내부 CRS를 기준으로 분석하며, 영상 래스터의 수직 CRS를 억지로 합성하지 않는다.
  • LAS와 PRJ의 복합 CRS는 구성 요소를 분해하여 수평 EPSG와 수직 기준을 각각 판정한다.
  • GTIFF_SRS_SOURCE=EPSG 같은 전역 환경 설정과 WKT 이름 기반 임의 매칭은 실제 실패 자료가 확보되기 전까지 추가하지 않는다.
  • 알려진 CRS만 선택적으로 정상화하고, 예상하지 못한 CRS 오류나 경고를 전역으로 숨기지 않는다.
  • Rasterio와 Pyproj가 사용하는 PROJ 버전 차이는 이번 결함의 직접 원인이 아니므로 패키지 변경 없이 검증 결과만 남긴다.

구현 체크리스트

  • 공통 CRS 정상화 함수에서 수평·수직 CRS 구성 요소를 분리한다.
  • 기존 epsg 필드가 복합 CRS에서도 수평 EPSG를 반환하도록 수정한다.
  • horizontal_crs, vertical_crs, crs_status 상세 메타데이터를 추가한다.
  • KNGeoid24 사설 코드가 custom_vertical_crs 상태로 정상 기록되는지 확인한다.
  • 현재 영구저장소의 TIFF가 EPSG:5187, 영상 자료로 유지되는지 확인한다.
  • 현재 영구저장소의 PRJ와 LAS가 수평 EPSG:5187 및 수직 KNGeoid24로 분리되는지 확인한다.
  • Python 정적 검사와 포맷 검사를 통과한다.
  • Graphify, 위키 인제스트, 위키 린트는 담당 AI 작업으로 남긴다.

수행 결과 (2026-07-18)

  • B03_FileInput_Engine_Analyze.pynormalize_crs_metadata()를 추가하여 GeoTIFF·PRJ·LAS가 동일한 CRS 메타데이터 구조를 사용하도록 변경했다.
  • 기존 epsg 필드는 복합 CRS 전체 코드가 아니라 수평 구성 요소의 EPSG를 반환한다. 따라서 KNGeoid24가 결합된 PRJ와 LAS도 epsg=5187로 DB에 저장할 수 있다.
  • 상세 판정 결과로 horizontal_crs, vertical_crs, crs_status를 추가했다. 상태는 identified, custom_vertical_crs, unknown_horizontal_crs, missing_crs로 구분한다.
  • KNGeoid24 WKT의 사설 EPSG:9995/99999 표식은 원문을 변경하지 않고 파싱용 WKT에서만 분리하며, custom_authority_codes에 원래 코드를 보존한다.
  • Rasterio가 GeoTIFF를 열 때 발생시키는 EPSG:9995/99999 crs not found 로그만 파일 오픈 구간에서 선택적으로 차단하고 B03 안내 로그로 변환했다. 다른 GDAL/PROJ 경고는 차단하지 않는다.
  • 동시 업로드 시 다른 작업의 로그를 잘못 차단하지 않도록 경고 필터를 생성한 스레드에서 발생한 메시지만 처리한다.
  • 실제 영구저장소 result.tif 검증 결과는 EPSG:5187, 4밴드 uint8, likely_type=image, crs_status=identified이며 수직 CRS를 영상 메타데이터에 합성하지 않았다.
  • 실제 result.prjcloud_merged.las 헤더 검증 결과는 수평 EPSG:5187, 수직 Korean National Geoid Model (KNGeoid24), crs_status=custom_vertical_crs이다.
  • 등록되지 않은 임의 수평 투영 CRS는 epsg=None, crs_status=unknown_horizontal_crs로 유지하여 EPSG를 추측하지 않는 것을 확인했다.
  • 현재 런타임은 Rasterio 1.5.0/PROJ 9.7.1과 Pyproj 3.7.2/PROJ 9.5.1이며, 재현 결함이 없어 패키지나 전역 GTIFF_SRS_SOURCE 설정을 변경하지 않았다.
  • ruff format, ruff check, python -m py_compile, 실제 저장 파일 기반 회귀 assertion, JSON 직렬화 검증을 통과했다.
  • CRS 검증과 무관한 1.7GB LAS classification 전수 스캔은 다시 실행하지 않고 LAS 헤더만 검증했다.
  • 사용자 요청에 따라 Graphify, 위키 인제스트, 위키 린트는 실행하지 않았으며 담당 AI의 후속 작업으로 남겼다.