# 관악산 Semi-MVP 1단계 Implementation Plan **Goal:** 고정 관측점의 실제 태양 위치를 KST 시간 제어와 FPS 시점으로 관찰한다. **Architecture:** 제공된 모듈 구조를 따르는 프레임워크 없는 Vite 앱. 천문 계산은 Three.js와 독립. 설정은 config/, 기능 상수는 constants/에 둔다. **Tech Stack:** TypeScript, Vite, Three.js Sky / PointerLockControls, SunCalc 2.x. **Spec:** 사용자가 제공한 Semi-MVP 1단계 작업지시서. ## 결정 및 범위 - 빈 폴더에 로컬 실행 프로젝트를 만든다. Git 저장소가 없어 worktree/커밋은 생성하지 않는다. - 임시 관측점: 37.4450 N, 126.9640 E, 해발 629 m, 눈높이 1.7 m. 측량값이 아님을 화면과 코드에 명시. - 표준 가상 지평선은 고도각 0°. 일출/일몰은 해발+눈높이로 보정하며 표준 0m 결과도 함께 표시한다. - KST 날짜의 정오를 getTimes에 전달해 자정에 전날 solar day가 선택되지 않게 한다. - 태양 원반은 0.53°, 광학 halo는 별도 셰이더. Sky 내장 원반은 비활성화해 중복 원반을 방지한다. - DEM, 지형, 건물, 이동, 백엔드, 호스팅은 범위 밖. ## 구현 및 검증 - [x] 천문/KST/방향 테스트를 먼저 작성하고 실패 확인. SunCalc 2.x 기반 계산 및 시간 모듈 구현. - [x] Sky, 원반/halo, 0° 지평선, 방위 표시, 고정 FPS 카메라 구성. - [x] 최소 한국어 UI와 실시간 1초 갱신, 날짜/슬라이더, 탭 복귀 재동기화 연결. - [x] NOAA 공개 수식의 독립 구현과 여러 계절/시각 대조. 허용 오차를 명시하고 결과 저장. - [x] TypeScript/production build, 18개 테스트, 브라우저 화면·시간 UI 검증. README에 실행법/제한 기록. - [ ] 일반 브라우저 Pointer Lock 회전 및 ESC 실제 확인: 내장 브라우저 거부, 일반 Chrome 자동화 URL 확인 실패로 미검증. ## 검토 및 실행 기록 - 독립 리뷰의 2건(과거 서울 시차 불일치, LIVE 중 날짜 편집 덮어쓰기)을 재현 테스트로 확인 후 수정. 입력과 출력 모두 IANA Asia/Seoul 사용. - NOAA 전 구간 0.1° 테스트는 지평선 아래 5개 사례에서 실패. SunCalc 음수 고도 굴절 입력 clamp를 확인해 표시 구간 0.1° / 비표시 고도 0.5°로 구분. 원본 차이를 검증표에 보존. - Vite 단일 번들 500 kB 권고 경고는 Three.js 포함으로 발생. 범위에 불필요한 지연 로딩은 추가하지 않음. ## 검토 초점 KST 자정, 방위각 래핑, 지평선 아래 원반 숨김, 고도 보정 일출과 0° 표시 구분, Pointer Lock 실패 안내. ## 추후 TODO (2026-10-30) - [ ] 서버 운영 단계에서 LIVE 모드를 서버 시간 기준으로 동기화한다. 현재는 구현을 보류한다. - 목적: 사용자 기기 시계의 오차 및 실행 중 시계 변경으로 인한 LIVE 시각 차이를 줄인다. - 접속 시 서버 시각을 받아 기준을 맞추고, 이후에는 `performance.now()`의 경과 시간을 더해 브라우저에서 매초 SunCalc를 계산한다. 서버에 매초 요청하지 않는다. - 탭 복귀 및 주기적 재동기화를 적용한다. 통신 지연 보정과 동기화 실패 시 처리 방식은 구현 시 결정한다. - CUSTOM 모드는 사용자가 선택한 날짜·시간을 유지하고, 입력·표시는 기존 `Asia/Seoul` 기준을 유지한다.