Files
DefVideo/agent-docs/2026-06-18_이슈별-해결정리.md
b23042 819065a8f5 UI 수정
기획안 반영 및 보완
2026-06-19 14:40:47 +09:00

109 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DefVideo — 이슈별 해결 정리
- **날짜**: 2026-06-18
- **작성 시각**: 14:00 KST
- **범위**: 폴더-구동 데이터화, RouteInfo 디자인 이식, StationBar 표시/레이아웃, 재생 커서 매끄러움
- **공통 원칙**: 모든 표시 데이터는 선택한 폴더에서 읽는다(하드코딩 0). 폴더 CSV에 없는 정보는 `<영상명>.route.json`. mock/dead 코드는 삭제하지 않고 보존.
---
## 1. 환경: Node 12 → 실행 실패 (`Unexpected token '?'`)
- **증상**: `npm run dev``??`(nullish) SyntaxError.
- **원인**: 시스템 Node 12. 프로젝트는 Node 20+ 필요(Vite/better-sqlite3 등).
- **해결**: nvm으로 Node 20 설치, `.nvmrc`(`20`) 추가, `node_modules` 재설치.
## 2. 환경: PM2 `errored` / `ffprobe ENOENT`
- **원인①**: FFmpeg 미설치 → 서버가 기동 직후 죽음.
- **원인②(버그)**: `checkFFmpegInstalled``ffprobe -version`**텍스트** 출력을 `JSON.parse` → 항상 실패해 "FFmpeg not found" 오탐.
- **해결**: `apt install ffmpeg`. 감지 함수를 JSON 파싱 대신 **exit code 0 확인**으로 수정(server/src/services/ffmpeg.ts). ecosystem.config.js는 `__dirname` 기준 상대경로 + PATH 명령어로 정리.
## 3. 한글 파일명 깨짐
- **원인**: 파일명이 CP949(EUC-KR) 인코딩(Windows 한글). 시스템 locale UTF-8이라 `???`.
- **해결**: `iconv`로 파일명 일괄 UTF-8 변환(내용은 멀쩡, 파일명만).
## 4. 클라이언트 빌드 실패 (`manualChunks is not a function`)
- **원인**: Vite 8(rolldown)은 `manualChunks`를 **함수 형식**만 허용. 기존은 객체.
- **해결**: `client/vite.config.ts``manualChunks` 객체 → 함수로 변경.
---
## 5. 폴더 선택 → 연관 데이터 자동 로드
- **요구**: "파일 선택"으로 영상 고르면 같은 폴더+`building/`의 측점·POI·center·srt를 함께 읽어 화면 세팅. 어떤 영상이든 동작.
- **제약**: `<input type=file>`로 고른 단일 파일은 브라우저 보안상 형제 파일을 못 읽음.
- **결정/해결**: **폴더 선택(webkitdirectory) + 클라이언트 파싱** 방식 채택.
- `client/src/utils/geoData.ts`: 폴더 파일들에서 드론CSV·측점·POI·center·route.json 파싱(UTF-8/EUC-KR 처리).
- `client/src/store/geoStore.ts`: 파싱 결과(frames/stations/pois/centerline/routeMeta/loaded) 보관.
- 영상은 `URL.createObjectURL`로 재생. **서버 업로드/저장 없음.**
## 6. 측점 패널(StationBar) 안 보임
- **원인**: 리팩터링 시 StationBar가 누락되어 여전히 서버 `/api/geo/*`를 직접 fetch → 폴더 데이터를 못 읽고, 서버 없으면 빈 화면.
- **해결**: StationBar를 다른 컴포넌트처럼 **geoStore 구독**으로 변경(서버 fetch 제거). 클라이언트 전체 live `/api/geo` fetch 0건 확인.
## 7. "폴더 선택 시 업로드되나?"
- **답**: 아니오. webkitdirectory의 **브라우저 경고 문구**일 뿐 전송 없음. 코드에 fetch/POST/FormData 0건, 전부 브라우저 메모리 파싱.
## 8. UI 정리: "파일 선택" 제거 / 도구·좌우 패널 숨김
- "파일 선택" 버튼 제거, **가운데 반투명 "폴더 선택"** 버튼 추가(`VideoPlayer.tsx`).
- 하단 도구 패널: `SHOW_TOOLBAR=false`**UI 숨김(코드 보존)**.
- 좌·우 패널: `SHOW_LEFT_PANEL`/`SHOW_RIGHT_PANEL=false`**UI 숨김(코드 보존)**.
## 9. StationBar 완전 폴더-구동화 (하드코딩/mock 제거)
- **원인**: 노선명·터미널명(신탄진/대전)·구조물·이정이 mock(`mocks/route.ts` ROUTE_LEGS, Timeline 하드코딩, segments.ts)에서 나옴.
- **해결**:
- `<영상명>.route.json`(routeInfo + structures) 도입 + 샘플 생성. geoStore `routeMeta`.
- 커서 이정 배지: mock `mileageAtPx` 제거 → 폴더 데이터(드론 GPS 투영 체이니지).
- 터미널명: route.json → 폴백 첫/끝 측점 title. Timeline 하드코딩 제거(props).
- 구조물: route.json `structures`(없으면 POI category 폴백).
- RoutePanel 양끝 라벨도 route.json 이름.
## 10. 좌상단 노선정보 배너 (videoplayer 디자인 이식)
- **요구**: 좌상단에 방향/노선명/연장/소요 배너.
- **과정**: 이모지 버전 → "느낌이 다름" → **videoplayer `RouteInfo` 1:1 이식**(배경이미지 `title-panel-bg@2x.png` + 절대좌표 + Noto Sans KR) → "크기 차이" → **영상 폭/1920 비율 스케일** 적용.
- **데이터**: 연장=route.json 우선→측점 구간 계산, 소요=route.json 우선→실제 영상 길이, 방향·노선명=route.json. (`RouteInfoOverlay.tsx`, `RouteInfo.module.css`)
## 11. 텍스트 배율 / 화면 채움
- **배율 질문**: 퍼블리싱(px+transform)은 텍스트 줌 무반응, DefVideo(Tailwind rem)는 반응. 사이니지엔 고정+화면비례 권장.
- **꽉 채움**: Video.js `fluid``fill`, `.vjs-fill/.vjs-tech { object-fit: cover }`, 오버레이 하단 앵커 → 검은 여백/하단 잘림 해결(`VideoPlayer.tsx`, `useVideoPlayer.ts`, `index.css`).
---
## 12. 커서 이정 10m 단위 표시
- **원인**: 배지가 최근접 측점 km(100m 양자화). `formatMileage`도 100m 반올림.
- **해결**: 연속 체이니지(`chain`) + `formatMileage10`(10m). 바 라벨은 **턴 지점만 10m**, 시·종점 등 기본은 100m.
## 13. 초반 감소구간이 주황(증가)으로 표시
- **원인**: 구간 방향 계산이 시작 방향을 `dir=1`(증가)로 가정.
- **해결**: 첫 유의미 이동(±100m)으로 **시작 방향을 실데이터 판정** → 감소면 하늘색.
## 14. 시설물(구조물) 표시 = videoplayer 아이콘
- **요구**: 텍스트만 → videoplayer 3-slice 아이콘으로, 재생바 위에 겹쳐, 통과 시 색 변경.
- **해결**:
- DefVideo에 이미 있던 `RouteSegment`(3-slice PNG, `public/assets/route-segment/`) 사용.
- 아이콘을 **재생바 위 레이어(z-index)** 에 배치(top≈바 중앙).
- **원본 치수 적용**: 교량 22×16/cap6/top32.5, 터널 24×14/cap10/top33.75.
- 라벨 폰트 **Noto Sans KR** 추가(`index.html`) — 글자 스타일 원본 일치.
- 커서가 아이콘 **좌측 끝에 닿는 순간** `passed`로 전환 → **아이콘+라벨 색 동시 변경**(neutral→accent).
---
## 15. 재생 커서가 끊김/물결/흔들림 (핵심 성능 이슈)
단계적으로 진단·수정:
1. **끊김(250ms 점프)**: `timeupdate`(250ms)로만 갱신 → rAF 도입.
2. **물결(출렁임)**: rAF 60fps로 `currentTime()`을 읽는데 미디어 시계는 29.97fps → 같은값→점프 반복. `requestVideoFrameCallback` 시도(여전히 프레임 단위 계단).
3. **흔들림 잔존(최종 해결)**: 원인 = **4K HEVC 디코딩 + 60fps React 리렌더 경쟁 + 보간 역방향 보정**.
- **단조(monotonic) 보간**: 벽시계 기반 보간, 작은 역행 무시(흔들림 제거), 뒤처짐/시크만 재동기화(`VideoPlayer.tsx`).
- **커서/진행바를 React에서 분리**: 라이브 시간(`smoothTimeRef`)을 StationBar가 rAF로 읽어 **CSS 변수(`--cursor-x`,`--pos-px`)만 직접 갱신**. React 상태는 배지/색용으로 ~10fps throttle.
- 커서 `left`→**`transform: translateX`**(GPU 합성, reflow 제거) + `will-change`. 진행바 폭은 CSS 변수 `calc()`.
- 결과: 합성 스레드에서 부드럽게 이동, 4K 디코딩 부하와 분리. **해결 확인됨.**
- **참고**: 비교 대상 videoplayer는 실제 영상이 없는 순수 애니메이션(17px/s)이라 본래 매끄러움. DefVideo는 실영상 동기라 위 최적화가 필요했음.
---
## 사용자 목적 적합성 확인
- "접속자가 자기 영상 폴더를 올려 재생" → **클라이언트 방식이라 사용자별 독립·무업로드로 적합.**
- 실전 점검: ① **HEVC 코덱 호환성(최우선)** ② 폴더 파일명 규칙 ③ CSV 인코딩.
## 토큰 사용량(추정)
- 본 세션 누적 ≈ **600k+ tokens** (오케스트레이터 + 서브에이전트 Explore×2/DEV×1). 정확 집계 도구 없어 추정.