This commit is contained in:
2026-07-10 18:12:17 +09:00
parent 50d75fcfcd
commit e3d66e717c
28 changed files with 2542 additions and 99 deletions
+388
View File
@@ -0,0 +1,388 @@
# 0_old vs 현재 프로젝트 혼선 지점 분석 (Critical for Coders)
**작성일:** 2026-07-10
**목적:** 0_old 코드 참고 시 발생할 수 있는 통합 오류 사전 차단
---
## 1. 데이터 구조 & 저장소 경로 차이
### 1.1 저장소 경로 구조
| 항목 | 0_old | 현재 프로젝트 |
|------|-------|------------|
| **기본 경로** | `storage/projects/{projectId}/` | `storage/{company_slug}/{user_slug}/{projectId}/` |
| **원본 입력** | `input/` (명확하지 않음) | `B03_FileInput/input/` |
| **처리 결과** | `processed/` (모든 것을 한곳에) | `B04_wf1_Surface/processed/` (분산) |
| **지표면 모델** | `processed/` 내 JSON | `B04_wf1_Surface/models/` |
| **경로 데이터** | `route_design/` | `B05_wf2_Route/route/` |
| **종횡단면** | `sections/` | `B06_wf3_ProfileCross/` |
**코더 주의:**
- 0_old의 경로를 그대로 현재 코드에 복사하면 **파일을 찾을 수 없음**
- 항상 `config_system.py``PROJECT_STORAGE_STAGE_DIRS` 확인
- 경로 변환은 `common_util_storage.py``resolve_stored_project_path()` 사용
**예시 오류:**
```python
# ❌ 0_old 방식
path = f"storage/projects/{projectId}/processed/tin.json"
# ✅ 현재 방식
from common_util.common_util_storage import resolve_stored_project_path
stored_path = await get_project_storage_relative_path(connection, projectId)
project_root = Path(resolve_stored_project_path(stored_path))
path = project_root / "B04_wf1_Surface" / "models" / "tin.json"
```
---
## 2. API 엔드포인트 & 요청/응답 구조
### 2.1 0_old API 엔드포인트
| 메서드 | 경로 | 목적 |
|--------|------|------|
| GET | `/api/projects/{projectId}/analysis` | 분석 결과 조회 |
| GET | `/api/projects/{projectId}/las-points` | LAS 포인트 샘플 조회 |
| GET | `/api/projects/{projectId}/all-points` | 모든 포인트 조회 |
| GET | `/api/projects/{projectId}/ground-points` | 지면 포인트만 조회 |
| POST | `/api/projects/{projectId}/analyze-ground` | 분석 실행 (동기) |
| GET | `/api/projects/{projectId}/terrain-models` | 지표면 모델 목록 |
| POST | `/api/projects/{projectId}/route/solve` | 경로 계산 |
| POST | `/api/projects/{projectId}/sections/generate` | 종횡단면 생성 |
### 2.2 현재 프로젝트 API 엔드포인트
| 메서드 | 경로 | 목적 |
|--------|------|------|
| POST | `/api/projects/{projectId}/surface/analyze` | 분석 실행 (비동기, **상태 저장**) |
| GET | `/api/projects/{projectId}/surface/status` | 분석 상태 및 진행률 조회 |
| GET | `/api/projects/{projectId}/surface/models` | 지표면 모델 목록 |
| GET | `/api/projects/{projectId}/surface/point-cloud` | 포인트 샘플 조회 |
| GET | `/api/projects/{projectId}/surface/ground-stats` | 지면 필터 통계 |
| POST | `/api/projects/{projectId}/files` | 파일 업로드 (다중) |
| POST | `/api/projects/{projectId}/upload-sessions` | 청크 업로드 세션 시작 |
| POST | `/api/projects/{projectId}/chunks` | 청크 업로드 |
| POST | `/api/projects/{projectId}/finalize` | 업로드 완료 |
**코더 주의:**
- 0_old의 `/api/projects/{projectId}/analyze-ground`**현재에 없음**
- 현재는 `/api/projects/{projectId}/surface/analyze` + `/api/projects/{projectId}/surface/status` 조합
- 0_old 코드 마이그레이션 시 **비동기 처리 방식 변경 필수**
---
## 3. 프론트엔드 기술 스택 차이
### 3.1 라이브러리 버전
| 라이브러리 | 0_old | 현재 프로젝트 | 비고 |
|-----------|-------|------------|------|
| React | 19.2.7 | **없음** | **critical diff** |
| React-DOM | 19.2.7 | **없음** | **critical diff** |
| lucide-react | 1.23.0 | **없음** | 아이콘 라이브러리 |
| THREE.js | 0.185.0 | 0.185.0 | ✅ 동일 |
| MapLibre-GL | 5.24.0 | **없음** | 지도 렌더러 |
| TypeScript | 6.0.3 | 5.x (확인 필요) | 버전 차이 가능성 |
**코더 주의:**
- 0_old의 모든 `.tsx` 컴포넌트는 **React 훅 기반**
- 현재 프로젝트는 **바닐라 TypeScript + DOM 조작**
- 0_old 컴포넌트를 현재 프로젝트에 복사하면 **즉시 오류** (React 불가)
### 3.2 필수 변환 규칙 (0_old → 현재)
#### React 훅 → 클로저 + 렌더 함수
```typescript
// ❌ 0_old (React 훅)
function PointCloudViewer({ projectId }: { projectId: string }) {
const [scale, setScale] = useState<number>(1.0);
useEffect(() => { /* initialization */ }, [projectId]);
return <div>...</div>;
}
// ✅ 현재 (바닐라 TS)
function createPointCloudViewer(projectId: string): HTMLElement {
let scale = 1.0;
const container = document.createElement('div');
const initialize = async () => { /* initialization */ };
initialize();
return container;
}
```
#### JSX → `createElement` (또는 템플릿 리터럴)
```typescript
// ❌ 0_old (JSX)
<button onClick={() => handleClick()}>Click me</button>
// ✅ 현재 (DOM 직접 생성)
const button = document.createElement('button');
button.textContent = 'Click me';
button.addEventListener('click', handleClick);
```
#### lucide-react 아이콘 → 인라인 SVG / 유니코드
```typescript
// ❌ 0_old (lucide-react)
import { FileUp } from 'lucide-react';
<FileUp size={24} />
// ✅ 현재 (유니코드 또는 SVG)
const icon = document.createElement('span');
icon.textContent = '📤'; // 또는 인라인 SVG
```
---
## 4. 분석 엔진 & 백엔드 알고리즘
### 4.1 0_old 분석 프로세스
**`0_old/backend/app/analyzer.py`:**
- `analyze_project()` — 동기식 전체 분석 실행
- LAS 로드 및 메타데이터 추출
- 포인트 클라우드 필터 적용 (CSF, PMF, RANSAC, grid_min_z)
- 지표면 모델 생성 (TIN, DTM, NURBS, implicit, meshfree 등)
- 결과를 `storage/projects/{projectId}/processed/analysis.json` 에 저장
**결과 저장 형식:**
```json
{
"timestamp": "2025-07-10T...",
"project_files": { /* file metadata */ },
"point_cloud_summary": { "total": 1000000, ... },
"ground_filter_results": { "csf": { ... }, "pmf": { ... }, ... },
"terrain_models": {
"tin": { "model_file": "...", "contours": [...] },
"dtm": { ... }
}
}
```
### 4.2 현재 프로젝트 분석 프로세스
**`B04_wf1_Surface/B04_wf1_Surface_Engine.py`:**
- `run_surface_analysis()` — 동기식이지만, 라우터에서 `asyncio.to_thread()` 로 실행
- 결과를 여러 개의 DB 테이블에 저장:
- `processed_point_clouds` 테이블
- `surface_models` 테이블
- `terrain_layers` 테이블
- 파일 경로도 함께 DB에 저장 (`model_file_path`, `layer_file_path` 등)
**코더 주의:**
- 0_old는 JSON 파일 중심, 현재는 **DB + 파일 경로 이원화**
- 분석 결과 조회 시:
- 0_old: `storage/projects/{projectId}/processed/analysis.json` 직접 읽기
- 현재: `surface_models` 테이블 쿼리 + 필요한 파일을 경로로 로드
---
## 5. 프론트엔드 상태 관리 & LocalStorage
### 5.1 0_old 상태 관리
**`main.tsx`에서 `useState` 사용:**
- `projectId` — 현재 프로젝트 ID
- `stage` — 현재 워크플로우 단계
- `analysisResult` — 분석 결과 캐시
- `selectedRoute` — 선택된 경로
- 등등
**localStorage 미사용** (또는 매우 제한적)
### 5.2 현재 프로젝트 상태 관리
**`config_frontend.ts`:**
```typescript
const CURRENT_PROJECT_ID_KEY = "frd_current_project_id";
```
**localStorage 의존성:**
- 프로젝트 ID는 반드시 localStorage에 저장
- 페이지 네비게이션 시 projectId 복구
- 청크 업로드 세션 정보도 localStorage 유지
**코더 주의:**
- 0_old 코드를 현재 프로젝트에 옮길 때, localStorage 복구 로직 추가 필수
- 특히 B04, B05, B06 페이지는 모두 `CURRENT_PROJECT_ID_KEY` 의존
---
## 6. 3D 렌더링 (THREE.js) — 유사성
### 6.1 공통점
**0_old와 현재 모두 THREE.js 0.185.0 사용:**
- `PointCloudViewer.tsx` → 포인트 클라우드 렌더링
- `TerrainModelViewer.tsx` → 지표면 모델 렌더링
- OrbitControls 사용 (카메라 조작)
**코더에게 좋은 소식:**
- THREE.js 부분은 상대적으로 간단한 변환 가능
- 렌더 루프, 조명, 카메라 로직은 큰 변경 불필요
- DOM 생성 부분만 수정하면 대부분 재사용 가능
**예시:**
```typescript
// ❌ 0_old (JSX)
<Canvas camera={{ position: [100, 100, 100] }}>
<mesh>...</mesh>
</Canvas>
// ✅ 현재 (THREE.js 직접)
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 10000);
camera.position.set(100, 100, 100);
const renderer = new THREE.WebGLRenderer();
renderer.render(scene, camera);
```
---
## 7. 필터 알고리즘 (Python) — 재사용 가능
### 7.1 0_old 필터 유틸리티
**`0_old/utils/` 디렉토리:**
- `filter_csf.py` — Cloth Simulation Filter
- `filter_pmf.py` — Progressive Morphological Filter
- `filter_ransac.py` — RANSAC-기반 필터
- `filter_grid_min_z.py` — Grid Min-Z 필터
**현재 프로젝트에서 이 필터들을 사용하는가?**
- ✅ 네, `B04_wf1_Surface_Engine.py`에서 참고
- 동일한 필터 알고리즘 재구현 가능
**코더 주의:**
- 필터 알고리즘은 그대로 복사 가능 (Python 코드)
- 하지만 **경로, DB 저장 방식은 변경 필수**
---
## 8. 라우팅 & 네비게이션 차이
### 8.1 0_old 라우팅
**`main.tsx`에서 React Router 미사용, 수동 state 관리:**
```typescript
if (stage === "TERRAIN_ANALYSIS") {
return <TerrainAnalysisStage />;
} else if (stage === "ROUTE_DESIGN") {
return <RouteDesignStage />;
}
// ...
```
### 8.2 현재 프로젝트 라우팅
**`A00_Common/A00_Common_UI_Navigator.ts`에서 수동 SPA 라우팅:**
```typescript
function navigateTo(route: string): void {
window.location.hash = route;
// ...
}
```
**코더 주의:**
- 0_old 코드를 현재에 적용할 때, `navigateTo()` 사용 필수
- localStorage 저장 + 네비게이션 순서 엄격 준수 (§2.2.2 참고)
---
## 9. 체크리스트 for Coders
0_old 코드를 현재 프로젝트에 통합할 때 반드시 확인:
### 파일 경로
- [ ] `storage/projects/...``storage/{company}/{user}/{projectId}/B0N_...` 변환
- [ ] 하드코딩된 경로 제거
- [ ] `resolve_stored_project_path()``PROJECT_STORAGE_STAGE_DIRS` 사용
### API 호출
- [ ] 엔드포인트 변경 (`/analyze-ground``/surface/analyze`)
- [ ] 비동기 처리 추가 (폴링 로직)
- [ ] 요청/응답 포맷 확인
### 프론트엔드 컴포넌트
- [ ] React 훅 → 클로저 + 렌더 함수 변환
- [ ] JSX → `createElement` 또는 템플릿 리터럴 변환
- [ ] lucide-react 아이콘 → 유니코드/인라인 SVG 변환
- [ ] localStorage 의존성 추가 (`CURRENT_PROJECT_ID_KEY`)
### 상태 관리
- [ ] `useState` 호출 제거
- [ ] localStorage에 상태 저장 확인
- [ ] 페이지 리로드 후 복구 로직 확인
### THREE.js 렌더링
- [ ] 캔버스 생성 부분 확인
- [ ] 렌더 루프 설정 확인
- [ ] 이벤트 리스너(resize, click 등) 추가
### DB 저장
- [ ] JSON 파일 저장에서 DB 테이블 저장으로 변경
- [ ] 파일 경로를 DB에 함께 저장
- [ ] 트랜잭션 처리 확인
---
## 10. 예시: 0_old PointCloudViewer 변환
### 0_old (React + JSX)
```typescript
// 0_old/frontend/src/PointCloudViewer.tsx (간략)
export function PointCloudViewer({ projectId }: { projectId: string }) {
const [scale, setScale] = useState(1.0);
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
const renderer = new THREE.WebGLRenderer({ canvas });
// 렌더링 설정
}, [projectId]);
return <canvas ref={canvasRef} />;
}
```
### 현재 프로젝트 (바닐라 TS)
```typescript
// B04_wf1_Surface/B04_wf1_Surface_UI_PointCloud.ts (신규)
export function createPointCloudViewer(projectId: string): HTMLElement {
let scale = 1.0;
const canvas = document.createElement('canvas');
const initialize = async () => {
const renderer = new THREE.WebGLRenderer({ canvas });
// 렌더링 설정
const response = await fetch(`/api/projects/${projectId}/surface/point-cloud`);
const data = await response.json();
// 포인트 클라우드 렌더
};
initialize();
return canvas;
}
```
---
## 11. 결론
| 영역 | 재사용 난이도 | 주의사항 |
|------|-----------|---------|
| **경로 구조** | 높음 | 전체 매핑 필요 |
| **API 엔드포인트** | 높음 | 비동기 처리 방식 변경 |
| **프론트엔드 컴포넌트** | 높음 | React → TS 변환 필수 |
| **필터 알고리즘** | 낮음 | 경로 변수만 수정 |
| **THREE.js 렌더링** | 낮음 | JSX → DOM 생성만 수정 |
| **DB 저장 로직** | 높음 | 완전 재작성 |
**최종 권장사항:**
1. 0_old는 **알고리즘 참고용**으로만 사용
2. 경로, API, 컴포넌트 구조는 **현재 프로젝트 표준 준수**
3. 통합 전 **단위 테스트** 작성 (경로 매핑, API 응답 검증)