Skip to content
yim2412Public

About

로켓 발사 & 위성 추적 데스크톱 앱 (pywebview + MapLibre GL)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

RL3D — 로켓 발사 & 위성 추적

v1.14.0 · 변경 이력 · tests

전 세계 로켓 발사를 2D 지도에 표시하고, 위성을 실시간으로 움직이게 보여주는 Windows 데스크톱 앱. 뉴스 상황판 감성의 다크 테마. pywebview + MapLibre GL 로 만든 단일 exe(설치 불필요).

RL3D 화면 — 발사 마커·위성 레이어·낮/밤 오버레이

위 화면(v1.7.0): 발사장 마커(클러스터), 위성 773개의 실시간 위치(stations+visual+GEO+GPS — 적도를 따라 늘어선 주황 점이 정지궤도 벨트), 낮/밤 오버레이, 다음 발사까지 카운트다운하는 상단 속보 티커, 하단 타임라인.

기능

  • 🗺 발사 지도 — 전 세계 발사장을 마커로 표시 (🔵예정 / 🟢성공 / 🔴실패 / 🟠부분실패)
  • 📋 상세 패널 — 마커 클릭 시 로켓·기관·참여 기관·미션·궤도·발사 시각·이미지·미션 설명. 참여 기관은 누구를 위한 발사인가를 말한다 — Rocket Lab → BlackSky (민간) · SpaceX → NRO (정부). 실패/지연 시 그 사유도 표시. 범주형 정보는 한국어로 표시
  • ▶ 중계 링크 · 발사 소식 — 발사별 유튜브/X 중계를 버튼 하나로 열고(기본 브라우저), 생중계 중이면 배지 표시. 지연·재조정·리프트오프 같은 소식 타임라인과 미션 패치·프로그램 태그·발사 윈도우·"이 발사대 N번째(올해 M)" 기록까지
  • 🛰 위성 상세 — 위성 클릭 시 고도·속도·궤도 주기·경사각·근지점~원지점·이심률을 실시간 갱신(넓은 클릭 영역으로 움직이는 점도 쉽게 선택)
  • 🔥 재진입 예보 — 궤도가 내려가는 물체는 이대로면 약 1일 뒤 재진입을 적고, 30일 안이면 재진입 임박 배지를 붙인다. SGP4 가 대기권에서 값을 못 내는 시점을 이진 탐색해 구한다(외부 데이터 불필요). 실측 2,926건 중 190건(6.5%). 가정을 같이 적는다 — 궤도를 올리는 기동은 계산에 없어서, ISS 처럼 기동으로 유지하는 물체에는 예보가 나오지 않는다
  • 🛰 궤도 데이터 관측 시각 — 지도의 점은 TLE 로 계산한 값이라 그 TLE 가 언제 관측됐는지가 정확도를 좌우한다. 상세에 3.8일 전 관측을 적고, 낡으면 경고 색으로 알린다(저궤도 3일 · 중·정지궤도 30일 — 실측에서 50일 된 TLE 는 저궤도 2,880km · 고궤도 73km 어긋났다). 최신 데이터를 못 받아 이전 데이터를 쓸 때도 그 사실을 말한다
  • 🕒 정보 갱신 시각 — 상세 패널에 27일 전 처럼, LL2 가 이 발사 정보를 마지막으로 고친 때를 적는다. 툴바의 N분 전 갱신(내가 받아온 때)과 다른 값이다. 예정 발사는 실측 중앙값이 27일이라 이 줄이 곧 일정을 얼마나 믿을 수 있나가 된다(실측 최장 3.2년 전).
  • 📡 속보 티커 — 임박한 예정 발사 카운트다운과 최근 발사 결과(성공/실패 배지 + "N시간 전")를 섞어 순환
  • 🚀 발사 임박 집중 화면 — T-60분 안쪽 발사가 있으면 지도 하단에 큰 카운트다운 카드(중계 버튼·발사장 보기). 발사 시각이 분 단위까지 확정된 발사만 띄운다(LL2 net_precision) — 날짜만 확정된 발사에 초 단위 카운트다운을 붙이면 없는 정밀도를 지어내는 셈이다. ✕ 로 닫으면 그 발사는 이 실행 동안 다시 뜨지 않는다
  • 👋 첫 실행 안내 — 처음 열면 지금 화면의 모수를 숫자로 말한다 (지금 지도에 2026년 발사 98건이 있습니다 (예정 48 · 지난 50)). 요청을 아끼려고 위성·히트맵· 과거 연도가 기본으로 꺼져 있다는 사실과 켜는 길(버튼 + 단축키)을 같이 보여주고, 한 번 닫으면 다시 뜨지 않는다. 과거 연도 요청은 버튼을 누를 때만 나간다
  • ⌨ 키보드 단축키 — / 검색 · S 사이드바 · R 새로고침 · T 시간대 · B 배경 지도 · C 통계 · G 위성 그룹 · A 아카이브 불러오기 · 1~4 결과 필터 · 5 위성 · 6 낮/밤 · 7 밀도 · Esc 열린 패널 닫기(위에 덮인 것부터) · ? 도움말. 입력 중에는 단축키가 동작하지 않는다. 툴바에서 ⋯ 로 접힌 배경·통계는 B·C 가 직통 경로다
  • 🔍 검색 / 필터 — 발사명·로켓·기관 검색(여러 단어는 단어마다 찾는다 — falcon starlink. 한글로도 찾는다 — 스페이스X·팰컨 스타링크·창정·한국), 결과별 on/off
  • ☰ 목록 사이드바 (발사 / 위성 / 관심 탭) — 발사 탭은 필터·검색·타임라인이 적용된 목록, 위성 탭은 이름·NORAD·소유국·종류 검색(중국·로켓 몸체·국제우주정거장). 행 클릭 시 해당 위치로 이동 + 상세 패널
  • 🌐 발사장 현지 시각 — 상세 패널에 그 발사장에서의 시각을 함께 적는다 (2026. 09. 10. 오전 08:42 GMT-7). 내 시각과 같으면 줄을 생략한다. 추가 API 요청 없음
  • 🚀 로켓 제원 · 부스터 이력 — 상세 패널에서 로켓의 길이·지름·이륙 질량·LEO/GTO 탑재량·이륙 추력·단 수·첫 비행과 통산 성적(통산 630회 · 성공 629 · 실패 1 · 연속 성공 332)을 본다. 공시 발사가와 LEO kg당 값도 함께 — 5,200만 달러 · LEO kg당 $2,281. 재사용 로켓의 경제성이 여기서 드러난다(실측 Electron $20,000/kg 대 Falcon Heavy $1,411/kg). 다만 공시가는 나라마다 채움이 크게 갈려(미국 49/55 · 중국 2/21) 합계·순위는 내지 않는다. 부스터가 배정된 발사는 B1080 · 29번째 비행 · 착륙 시도 예정 · A Shortfall of Gravitas 처럼 재사용 이력까지. 착륙 통산도 함께 — 착륙 620회 시도 · 성공 615 (99%) · 연속 315. 기관 관점 화면에는 그 기관의 착륙 성적을 낸다. 착륙을 안 하는 소모형 운용사는 줄이 아예 없다. 추가 API 요청 없음(이미 받아오던 응답에 들어 있다)
  • 🏗 발사대 재사용 간격 · 발사장 통산 — 상세 패널의 기록 줄에 직전 발사로부터 2.8일 만 · 이 발사장 통산 912번째(올해 60). 네 축(발사대·발사장·기관·전 세계)이 통산과 올해를 함께 말한다 — 전에는 축마다 한쪽만 말해 기준이 다른 숫자가 나란히 섰다. 발사장 관점 화면에는 통산 회수를 모수로 밝힌다 (이 발사장은 통산 912회 발사했습니다 — 그중 14건(2%)을 불러왔습니다). 실측 범위가 2.79일 ~ 1541일이라 크기에 따라 단위를 바꿔 적는다
  • 🛫 관점 화면 (발사장 · 기관 · 로켓 · 계열) — 상세 패널의 발사장·기관·로켓 이름을 클릭하면 그 대상만의 총 발사·성공률과 구성 막대(발사장은 로켓·기관·패드별, 기관/로켓은 로켓·발사장·연도별) + 예정/최근 발사 목록
  • 🚀 로켓 계열 — 로켓 이름은 변형까지 담고 있어 Falcon 9 Block 5 와 Falcon Heavy 가, Long March 10종이 서로 남남이었다. 상세 패널의 계열 Falcon · 변형 2종 › 으로 계열 전체를 모아 보고, 변형별 막대로 그 계열에 무엇이 있는지 본다. 변형이 하나뿐이거나 데이터에 계열이 없는 로켓(Electron 등)은 줄이 아예 없다 — 로켓 화면과 같은 목록을 두 번 보여주지 않는다
  • 🗓 "언제인지 모르는" 발사는 그렇게 말한다 — 예정 발사의 78%는 LL2 가 달·분기·연 단위로만 주는 일정이다. 그런 발사는 초 단위 카운트다운 대신 2026년 10월 중 · 2026년 4분기 중 처럼 아는 만큼만 적는다 (날짜만 확정된 것은 T-3일 · 내일 중)
  • 🔁 연타해도 요청은 한 번만 — 새로고침·아카이브·위성은 이전 요청이 아직 안 왔으면 다시 보내지 않는다 (이미 갱신 중입니다). 발사 API 는 시간당 약 15회 제한이라 연타가 곧 예산이다. 자동 갱신과 수동 갱신이 겹쳐도 나중 것이 이긴다 — 늦게 도착한 옛 응답 때문에 화면이 되돌아가지 않는다
  • ⚠ 화면 밖으로 밀려난 발사를 말한다 — 상세를 열어 둔 채 검색·필터·타임라인으로 그 발사가 걸러지면 패널 맨 위에 그 사실을 적고, 지도에 남던 상승 궤적 점선도 함께 내린다. 갱신으로 목록에서 아예 빠진 경우는 "마지막으로 받은 내용" 이라고 따로 말한다
  • ⭐ 관심 발사 · 위성 — 상세 패널의 ☆ 관심으로 담아두면 지도에서 금색으로 강조되고 사이드바 ⭐ 관심 탭에 모인다. 다음 실행에도 유지
  • 🕒 발사 순서표 — 상세 패널에서 그 발사의 진행 순서를 본다(T-38:00 추진제 주입 승인 … T±0:00 리프토프 … T+2:26 1단 엔진 정지(MECO) … T+8:26 1단 착륙). 발사 시각이 분 단위까지 확정된 발사만 절대 시각을 함께 적는다 — 날짜만 확정된 발사에 초 단위 시계를 붙이면 없는 정밀도를 지어내는 셈이다. **집중 화면에는 "지금 어느 단계"**가 매초 갱신된다(리프토프 지남 · 다음 최대 동압(Max-Q) T+1:07 · 12초 뒤). LL2 가 주는 발사사 공개 계획이라 실측 중계가 아니며, 실측 100건 중 35건에만 있다(대부분 지난 발사) — 없으면 블록을 안 그린다
  • 🚀 발사 궤적 근사선 — 발사 상세를 열면 지도에 상승 경로를 점선으로 근사해 그린다. 발사장 좌표와 목표 궤도 경사각으로 방위각을 풀어(sin A = cos i / cos φ) 대권을 약 2,200km 따라간다. 실측이 아니다 — 그래서 "근사입니다" 대신 가정을 숫자로 적는다(가정: 경사 98.0°(태양동기) · 방위 203° 남서쪽). 저궤도처럼 이름만으로 경사를 알 수 없는 경우(전체의 약 57%)에는 최소 에너지로 가정하고 그 사실을 함께 밝힌다. 탄도 비행(Suborbital)은 궤도 진입이 없어 그리지 않는다
  • 🔥 발사 밀도 히트맵 — 툴바 밀도(또는 7)로 켠다. 마커·클러스터는 "어디서 몇 번"을 못 보여준다 — 같은 발사장에 완전히 겹친 점은 1건이나 300건이나 똑같이 보이기 때문. 지금 보고 있는 필터 결과에만 반응하며, 색 눈금은 데이터에 맞춰 다시 잡힌다(한 발사장 최다 건수가 램프의 끝). 범례에 1건 ~ 최다 N건 눈금과 모수(불러온 건수·기간·부분 표본 연도)를 함께 적는다 — 아카이브를 안 불러오면 최근 100건짜리 얼룩을 "발사 중심"으로 읽게 되기 때문. 아카이브를 불러올수록 뚜렷해진다
  • 🕓 시간대 전환 (현지 ↔ UTC) — 이 앱은 시간이 핵심인데(카운트다운·발사 윈도우·순서표·통과 예측) 어느 시간대인지 어디에도 적혀 있지 않았다. 툴바 버튼(🕓GMT+9 / 🕓UTC)이 지금 쓰는 시간대를 상시 표시하고, 누르거나 T 로 UTC 와 오간다. 발사 시각·윈도우·순서표·통과 예측·타임라인 라벨이 모두 같은 스위치를 따르며, 바꾸면 이미 열려 있는 패널도 다시 그린다. 설정에 저장된다
  • 🗺 배경 지도 전환 — 다크 ↔ 위성사진(둘 다 Esri). 툴바에서 전환, 설정에 저장
  • 🗄 과거 발사 아카이브 — 타임라인 옆에서 연도(최근 5년) 선택 후 불러오면 그 해 발사가 지도·목록·타임라인에 추가됨. 지난 연도는 영구 캐시(재요청 없음). 연도당 페이지 상한(500건)에 걸리면 잘렸다고 알리고, 그 해는 통계에서도 부분 표본으로 센다
  • 📊 발사 통계 — 총 발사·성공률·예정 요약 + 결과별/연도별/기관/국가 막대. 모수를 함께 밝힌다: 포함된 기간, 성공률의 분모(결과 확정 N건), 그리고 어느 해가 부분 표본인지. 여기에 더해 표본이 전체의 얼마인지까지 적는다 — 2026년 전 세계 궤도 발사 지금까지 215건 — 그중 49건(23%)을 불러왔습니다 · 예정까지 포함하면 연말 356건. LL2 의 연내 궤도 발사 순번이 유일한 외부 기준값이고, 이미 일어난 발사와 예정 발사를 나눠 센다(예정 번호를 섞으면 "지금까지 356건 발사됐다"는 거짓말이 된다). 라이브 데이터는 최근 발사 50건 + 예정뿐이라 아카이브를 안 불러온 해는 2026 (일부) 로 표시된다
  • 🛰 위성 그룹 선택 — stations·visual·Starlink·GPS·Galileo·기상·과학·GEO 토글. Starlink만 2,000개 상한(전체 10,000여 개를 거듭 받으면 Celestrak이 요청을 막는다), 나머지는 전부 표시
  • 🛰 궤도 대역 필터 — 툴바 그룹 ▾ 안에서 저궤도(LEO)·중궤도(MEO)·정지궤도(GEO)를 켜고 끈다. 이미 받아둔 TLE만 걸러내므로 재요청 없이 즉시 반영되고, 툴바에 (보이는 수/전체)로 표시된다(관심 위성은 필터와 무관하게 남는다)
  • ⬆ 새 버전 확인 — 시작할 때 GitHub 최신 릴리스를 확인하고, 지금 버전보다 높으면 지도 좌하단에 안내 배지. 누르면 릴리스 페이지가 열리고 ✕ 는 그 버전만 닫는다(다음 버전이 나오면 다시 뜬다). 하루 1회만 확인하며, 실패해도 화면에는 아무 영향이 없다
  • 🕒 갱신 시각 표시 / 설정 저장 — "N분 전 갱신" 상시 표시. 필터·토글·위성 그룹·궤도 대역·관측 위치·관심 목록·지도 위치·창 위치/크기를 저장해 다음 실행에 복원
  • 🔄 자동 갱신 — 5분마다 백그라운드 폴링, 새 발사·상태 변화(예정→성공 등)를 화면 하단에 표시
  • 🛰 위성 레이어(선택) — Celestrak TLE + satellite.js(SGP4)로 위성 실시간 위치. 기본 OFF, 툴바에서 켜기. 켜 두면 TLE 도 발사와 같은 주기로 다시 받는다(실제 호출은 캐시 TTL 2시간이 제어) — 보던 위성의 선택·추적은 유지된다. 점 색이 궤도 대역을 나타낸다(저궤도 하늘색 → 중궤도 보라 → GPS 대역 분홍 → 정지궤도 주황)
  • 🛰 지상궤적선 · 추적 모드 · 미래 위치 — 위성 클릭 시 약 1주기의 지상궤적선을 표시, "추적" 버튼으로 지도 중심을 위성에 고정(지도를 직접 드래그하면 해제). 슬라이더로 "앞으로 볼 시간"(0~6시간)을 늘리면 궤적이 그만큼 앞으로 이어지고, 그 시각 위치에 2시간 뒤 배지가 선다. 확대돼서 배지가 화면 밖일 때를 대비해 컨트롤에 좌표도 함께 표시된다
  • 🌓 낮/밤 오버레이 — 현재 태양 위치로 야간 반구를 음영 처리(외부 데이터 없이 계산, 분 단위 갱신). 툴바에서 켜고 끄기, 기본 ON
  • 📍 관측 위치 지정 — 📍 관측 버튼(또는 오늘 밤 탭의 안내 버튼)에서 도시 이름 검색 · 좌표 직접 입력 · 지도 클릭 중 아무 방법이나 쓴다. 도시 목록은 앱에 번들돼 있어(한국 29곳 + 세계 주요 도시) 요청이 0이고 오프라인에서도 된다. 이미 불러온 발사장도 함께 검색된다 — "케네디 우주센터에서 보면 어떤가"를 바로 볼 수 있다(발사장은 케네디·바이코누르·나로 처럼 한글로도, 중국 처럼 나라로도 찾는다)
  • 📍 통과 예측 — 관측 위치 기준 → 선택한 위성의 향후 24시간 통과(시각·방위·최대고도)를 계산. 외부 API 없이 satellite.js로 계산, 관측 위치는 저장됨
  • 🌙 오늘 밤 탭 — 향후 24시간 안에 눈으로 볼 만한 통과를 모아 최대고도 순으로 보여준다. 저궤도만 센다 — 정지궤도·GPS 대역은 육안 대상이 아니고(등급 10 이상), 계산은 오히려 더 비싸다. 위성을 많이 켜 두면 계산이 길어지므로 조각으로 나눠 돌며 진행률을 보여준다(앱이 멈추지 않고, 탭을 옮기면 취소된다). 실측: 저궤도 2,256건 약 1분 · 한 조각 약 0.3초

실행

# 개발 실행
python main.py

# exe 빌드 → dist\RL3D.exe
build.bat

의존성: pip install -r requirements.txt (pywebview, pyinstaller, pythonnet[win]). Python 3.10+ 권장.

개발 테스트 (2번 모니터)

$env:RL3D_DEV_MONITOR = "2"
.venv\Scripts\pythonw.exe main.py   # 창을 2번(보조) 모니터에 · 콘솔 창 없이

RL3D_DEV_MONITOR 환경변수는 개발 테스트용이며 배포 exe 에는 영향이 없다. python.exe 가 아니라 pythonw.exe 로 띄운다 — python.exe 는 앱 창과 별개로 콘솔 창을 띄우고, 그 콘솔은 RL3D_DEV_MONITOR 와 무관하게 주 모니터에 뜬다. 로그는 콘솔이 아니라 %APPDATA%\RL3D\logs\ 에 남으므로(P12-9) 콘솔이 없어도 잃는 정보가 없다.

데이터 소스

데이터 출처 캐시 TTL
발사 Launch Library 2 (thespacedevs) 15분
과거 발사 아카이브 Launch Library 2 (연도별) 지난 연도 영구 · 올해 6시간
위성 TLE Celestrak (그룹 선택: stations/visual/starlink/gps 등) 2시간
위성 메타데이터 Celestrak SATCAT — 타입·소유국·발사일·발사장·크기 24시간
  • 캐시 위치: %APPDATA%\RL3D\cache\ (launches.json, tle_<그룹>.json, archive_<연도>.json, 한도 대기 기록 backoff.json)
  • 설정 위치: %APPDATA%\RL3D\settings.json (필터·토글·위성 그룹·관측 위치·창 상태)
  • 로그 위치: %APPDATA%\RL3D\logs\rl3d.log (512KB×4 회전, UTF-8). 앱이 겪은 실패가 여기 남는다
    • 화면(JS) 쪽 오류도 여기 남는다(rl3d.web 이름으로, v1.47.0). 전에는 앱이 조용히 죽어도 화면에도 로그에도 아무것도 안 남았다. 같은 오류는 60초에 한 번·세션 50건까지만 기록한다 — 억제가 없으면 매초 도는 계산의 예외 하나가 약 2시간 만에 로그를 전부 덮어 최초 증거를 지운다
    • 앱 안에서 오류가 나면 지도 위에 배너가 한 번 뜨고 이 로그 경로를 알려 준다
  • LL2 는 시간당 약 15회 제한 → 캐싱 우선. API 실패 시 오래된 캐시라도 반환(오프라인 대응)
  • 실패하면 쉬었다 다시 한다 — LL2 는 30분, Celestrak 은 2시간 동안(그룹별) 다시 요청하지 않고 가진 데이터와 직전 오류를 보여 준다. 예전에는 5분 폴링마다 다시 때려 429 가 풀리지 않았다(전면 감사 F-004)
    • 앱을 다시 켜도 쉼이 이어진다(v1.65.1) — 전에는 메모리에만 있어 껐다 켜면 곧바로 다시 요청했다
    • 쉬는 동안 화면은 얼마나 남았는지 말한다: 약 N분 뒤 자동으로 다시 받습니다.(v1.65.7~8)
  • 저장된 데이터는 배경 지도를 기다리지 않는다(v1.65.0) — 발사·위성은 지도가 준비되는 즉시 뜨고, 배경 타일은 따로 들어온다. 전에는 타일을 다 받을 때까지 기다려 창이 뜬 뒤 20~33초 동안 비어 있었다
  • 새로고침 버튼: 캐시 무시 강제 갱신. 단 방금(60초 안) 받은 데이터가 있으면 요청하지 않는다
  • 🧭 각 화면이 무엇을 센 숫자인지 밝힌다(v1.50.0) — 통계 패널은 불러온 441건 전체 기준, 밀도 범례는 지금 보이는 378건 기준, 관점 화면은 이 화면 대상의 14건 기준. 세 곳이 예전엔 같은 문장을 썼다 (통계는 검색·필터와 무관하게 전체를 센다 — 그래야 성공률 같은 수치가 뜻을 갖는다). 속보 띠도 필터와 무관하며, 그럴 때만 전체 기준 표시가 뜬다
  • 🔢 순번은 날짜가 확정된 발사에만(v1.49.0) — 이 발사장 통산 273번째 같은 순번은 이미 일어난 발사와 날짜가 잡힌 예정 발사에만 붙는다. "연말까지 언젠가"인 발사들은 서로 같은 번호를 받아 오기 때문이다 (실측: 한 번호를 최대 23건이 공유). 예정이면 예정 기준 — 을 앞에 붙여 아직 안 일어낚c음을 밝힌다
  • 📍 한 점에 포개진 발사(v1.48.0) — 같은 발사대에서 쏜 발사는 지도에서 정확히 같은 점에 그려진다 (실측: 한 점에 최대 86건 · 전체의 97% 가 겹치는 점 위에 있다). 그런 점을 누르면 그 지점의 발사 목록이 열리고, 한 줄을 누르면 상세로 간다. 1건뿐인 점은 예전처럼 바로 상세가 열린다. 툴팁도 이 지점 86건 이라고 먼저 알려 준다

⚠ 온라인/오프라인

  • MapLibre GL·satellite.js 라이브러리와 세계 해안선(Natural Earth 50m, 퍼블릭 도메인)은 exe 안에 오프라인 번들(web/lib/)로 포함
  • 단 지도 배경 타일(Esri Dark Gray Canvas · Esri World Imagery)과 발사/위성 데이터는 인터넷 연결이 필요하다
  • 오프라인이면 발사·위성은 저장된 캐시로 그대로 뜨고, 배경 타일 대신 번들된 해안선 실루엣이 남는다 — 발사장·위성이 어디인지는 계속 읽힌다. 지도 좌하단에 안내 배지가 나타난다 (눌러서 닫을 수 있고, 연결이 돌아와 타일이 받아지면 스스로 사라진다)
  • 해안선은 저해상도라 확대하면 각진다 — 배경 타일의 대체가 아니라 오프라인 때의 뼈대다. 고해상도 타일 번들은 라이선스상 불가하다(Esri 는 "다른 앱을 통해 오프라인용으로 타일을 조직적으로 요청하는 것" 을 금지한다)

터미널 스모크 / 테스트

python api_client.py            # 데이터 소스별 [OK]/[FAIL]·건수 확인 (GUI 없이, 네트워크 필요)
python satcat_codes.py          # 위성 코드→사람 말 표 확인 (네트워크 불필요)
python applog.py                # 로그 파일 경로·기록 확인 (네트워크 불필요)
python startup.py               # 이 PC 의 WebView2 런타임 버전 확인 (네트워크 불필요)
python tests/test_parsing.py    # 파이썬 정규화 회귀 테스트 (픽스처 기반, 네트워크 불필요)
node tests/test_frontend.js     # 프론트엔드 회귀 테스트 (브라우저·네트워크 불필요)
python tests/test_cache.py     # 캐시·TTL·폴백·아카이브·설정 회귀 (네트워크 불필요)
node tests/test_docs.js        # 문서가 코드와 같은 말을 하는지 (파일 개수·순서·명령·버전)
node tests/test_layout.js      # 버튼이 다른 오버레이에 가리지 않는지 (헤드리스 Edge, 네트워크 불필요)
node tests/test_future.js      # 시계를 45·400·3650일 밀어도 프론트 테스트가 통과하는지 (날짜 시한폭탄)

회귀 테스트는 네트워크가 필요 없어 GitHub Actions 에서도 그대로 돈다 (.github/workflows/tests.yml — push·PR 마다 windows-latest 에서 실행). api_client.py 스모크는 네트워크를 쓰므로 CI 에 넣지 않았다.

파싱 회귀 테스트는 tests/fixtures/에 저장한 실제 API 응답을 파싱해 tests/golden/의 기대 결과와 비교한다. 외부 API가 필드를 바꾸거나 파싱을 잘못 건드리면 여기서 잡힌다.

프론트엔드 테스트(530항목)는 web/js/*.js를 로드 순서대로 이어 붙여 Node vm에 스텁 DOM과 함께 올리고 함수를 직접 호출한다(마우스 자동화 없음). 대상은 깨져도 화면상으로는 알아채기 어려운 로직 — 궤도 대역 분류·필터·검색·타임라인, 설정 복원 방어, 오프라인 판정, 통계 집계, 사이드바 정렬, 그리고 실제 SGP4로 검증하는 지상궤적선(날짜변경선 끊기)과 통과 예측이다. 통과 예측은 정답표가 없으니 물리 불변식으로 확인한다(경사 51.6° 위성은 남극에서 통과 0건, 통과 간격은 궤도 주기의 정수배 근처 등). 로딩·스텁은 tests/harness.js 한 곳에 있다.

python tests/capture_fixtures.py     # 픽스처 새로 받기(네트워크·LL2 요청 소모)
python tests/test_parsing.py --update # 골든 갱신(픽스처를 새로 받은 뒤에만)

요구 사항

  • Windows 10/11 — WebView2 런타임 필요(대부분 기본 내장). 없으면 실행 시 설치 안내가 뜬다. 안내를 닫으면 창은 뜨지만 내용이 빈 화면이다 — WebView2 Runtime 설치 후 다시 실행

실시간 발사 텔레메트리에 대하여

발사 순간의 실시간 고도/속도 텔레메트리를 제공하는 무료 공개 API는 사실상 없다(SpaceX 등도 웹캐스트 영상뿐). 본 앱의 "실시간"은 발사 일정·상태의 자동 갱신(위 자동 갱신 기능)으로 구현했다. 과거 발사 텔레메트리 기록은 Launch-Dashboard-API 같은 오픈소스가 있으나 라이브가 아니다.

개발 노트

만들면서 무엇이 어떻게 깨졌고 어떻게 알아냈는지를 docs/notes/ 에 두 편으로 적었다. 화면 대부분이 지도라, 틀리는 방식도 "아무것도 안 보인다" 쪽으로 몰렸다.

노트
01 고장이 아닌데 고장으로 보였다 — 정상 동작의 조합이 빈 화면을 만드는 일곱 가지 경로
02 공허하게 통과한 검사들 — 좌표가 전부 NaN 인데 every() 가 참이었다

고르고 남은 후보 34건과 왜 안 골랐는지는 CANDIDATES.md. 다섯 프로젝트의 공개 색인은 https://yim2412.github.io 에 있다.

라이선스

PolyForm Noncommercial 1.0.0 — 비상업 목적의 사용·수정·공유는 자유, 상업적 이용은 금지된다. 2026-10-05 전에 공개된 커밋은 그때의 MIT 조건이 그대로 남는다.

번들된 서드파티 라이브러리는 각자의 라이선스를 따른다 — MapLibre GL JS(BSD-3-Clause), satellite.js(MIT), 그리고 exe 에 함께 들어가는 파이썬 패키지(pywebview·pythonnet 등). 전문은 THIRD_PARTY_LICENSES.txt 에 있고 exe 안에도 함께 들어간다(tools/build_licenses.py 가 빌드 때 생성). 발사/위성 데이터는 각 제공처(thespacedevs, Celestrak)의 이용 조건을 따른다.

파일 구조

RL3D/
├── main.py          pywebview 창 + Api 브릿지 (로그·시작 진단 배선도 여기서만)
├── api_client.py    LL2 발사 + Celestrak TLE 호출·정규화·캐싱
├── applog.py        로그 파일 설정(%APPDATA%\RL3D\logs\, 회전)
├── satcat_codes.py  SATCAT 코드→사람 말 표(타입·소유국·발사장)
├── startup.py       WebView2 부재 안내 · 시작 실패 안내
├── build.bat        exe 빌드
├── requirements.txt
├── tests/           파싱 회귀 테스트 + 픽스처/골든, 프론트 회귀 테스트
└── web/
    ├── index.html · style.css
    ├── js/          state · utils · map · launches · sats · panels · settings · boot
    │                (클래식 스크립트 — index.html 의 로드 순서가 곧 의존 관계)
    └── lib/         maplibre-gl(.js/.css), satellite.min.js (오프라인 번들)

About

로켓 발사 & 위성 추적 데스크톱 앱 (pywebview + MapLibre GL)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages