7.9 KiB
7.9 KiB
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/geofetch 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.tsROUTE_LEGS, Timeline 하드코딩, segments.ts)에서 나옴. - 해결:
<영상명>.route.json(routeInfo + structures) 도입 + 샘플 생성. geoStorerouteMeta.- 커서 이정 배지: mock
mileageAtPx제거 → 폴더 데이터(드론 GPS 투영 체이니지). - 터미널명: route.json → 폴백 첫/끝 측점 title. Timeline 하드코딩 제거(props).
- 구조물: route.json
structures(없으면 POI category 폴백). - RoutePanel 양끝 라벨도 route.json 이름.
10. 좌상단 노선정보 배너 (videoplayer 디자인 이식)
- 요구: 좌상단에 방향/노선명/연장/소요 배너.
- 과정: 이모지 버전 → "느낌이 다름" → videoplayer
RouteInfo1: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).
- DefVideo에 이미 있던
15. 재생 커서가 끊김/물결/흔들림 (핵심 성능 이슈)
단계적으로 진단·수정:
- 끊김(250ms 점프):
timeupdate(250ms)로만 갱신 → rAF 도입. - 물결(출렁임): rAF 60fps로
currentTime()을 읽는데 미디어 시계는 29.97fps → 같은값→점프 반복.requestVideoFrameCallback시도(여전히 프레임 단위 계단). - 흔들림 잔존(최종 해결): 원인 = 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 디코딩 부하와 분리. 해결 확인됨.
- 단조(monotonic) 보간: 벽시계 기반 보간, 작은 역행 무시(흔들림 제거), 뒤처짐/시크만 재동기화(
- 참고: 비교 대상 videoplayer는 실제 영상이 없는 순수 애니메이션(17px/s)이라 본래 매끄러움. DefVideo는 실영상 동기라 위 최적화가 필요했음.
사용자 목적 적합성 확인
- "접속자가 자기 영상 폴더를 올려 재생" → 클라이언트 방식이라 사용자별 독립·무업로드로 적합.
- 실전 점검: ① HEVC 코덱 호환성(최우선) ② 폴더 파일명 규칙 ③ CSV 인코딩.
토큰 사용량(추정)
- 본 세션 누적 ≈ 600k+ tokens (오케스트레이터 + 서브에이전트 Explore×2/DEV×1). 정확 집계 도구 없어 추정.