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

7.9 KiB
Raw Permalink Blame History

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 미설치 → 서버가 기동 직후 죽음.
  • 원인②(버그): checkFFmpegInstalledffprobe -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.tsmanualChunks 객체 → 함수로 변경.

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=falseUI 숨김(코드 보존).
  • 좌·우 패널: SHOW_LEFT_PANEL/SHOW_RIGHT_PANEL=falseUI 숨김(코드 보존).

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 fluidfill, .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.
    • 커서 lefttransform: translateX(GPU 합성, reflow 제거) + will-change. 진행바 폭은 CSS 변수 calc().
    • 결과: 합성 스레드에서 부드럽게 이동, 4K 디코딩 부하와 분리. 해결 확인됨.
  • 참고: 비교 대상 videoplayer는 실제 영상이 없는 순수 애니메이션(17px/s)이라 본래 매끄러움. DefVideo는 실영상 동기라 위 최적화가 필요했음.

사용자 목적 적합성 확인

  • "접속자가 자기 영상 폴더를 올려 재생" → 클라이언트 방식이라 사용자별 독립·무업로드로 적합.
  • 실전 점검: ① HEVC 코덱 호환성(최우선) ② 폴더 파일명 규칙 ③ CSV 인코딩.

토큰 사용량(추정)

  • 본 세션 누적 ≈ 600k+ tokens (오케스트레이터 + 서브에이전트 Explore×2/DEV×1). 정확 집계 도구 없어 추정.