바로 전 커밋(routing.ts 고도 보간)이 README의 "0으로 폴백" 설명과 어긋나게 돼서, 실제 동작(주변 앵커 보간 우선, 정말 모를 때만 0)에 맞게 문구 갱신. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
108 lines
6.6 KiB
Markdown
108 lines
6.6 KiB
Markdown
<picture>
|
|
<source media="(prefers-color-scheme: dark)" srcset="website/static/logo-dark.svg">
|
|
<img alt="Logo of gpx.studio." src="website/static/logo.svg">
|
|
</picture>
|
|
|
|
[**gpx.studio**](https://gpx.studio)는 GPX 파일을 만들고 편집하는 온라인 도구입니다.
|
|
|
|
이 저장소는 [gpxstudio/gpx.studio](https://github.com/gpxstudio/gpx.studio)를 클론해서
|
|
**개인 NAS(Synology)에 자체 호스팅**하기 위해 커스터마이징한 포크입니다.
|
|
|
|
- 배포 주소: `https://gpx.dodo-lab.kr`
|
|
- 배포 방식: `website/`를 정적 빌드해서 Synology Web Station으로 서빙
|
|
|
|
## 원본 대비 변경 사항
|
|
|
|
### 기능 추가
|
|
- **자동차(Car) 라우팅 프로파일 추가** — BRouter(`car-fast`)를 이용, 기존 GraphHopper 기반 프로파일들과 별개로 동작
|
|
([routing.ts](website/src/lib/components/toolbar/tools/routing/routing.ts))
|
|
- **GPS 끊김 구간 자동 강조 기능** — 연속된 두 포인트 사이 거리가 최근 구간들의 중앙값 대비 3배 이상(그리고 15m 이상) 벌어지면
|
|
트랙 색상의 보색으로 자동 강조 표시. View 메뉴에서 켜고 끌 수 있음(기본 켜짐)
|
|
([gpx-layer.ts](website/src/lib/components/map/gpx-layer/gpx-layer.ts))
|
|
- **한국어(ko) 완전 번역** — UI 문자열(`ko.json`)과 도움말 문서(`/help`) 전체 20개 페이지 번역,
|
|
언어 선택 목록에 노출 ([languages.ts](website/src/lib/languages.ts))
|
|
|
|
### 버그 수정
|
|
- `[[language]]` 라우트 파라미터를 검증 없이 동적 import에 사용하던 문제 수정 — `/favicon.ico` 등 알 수 없는 경로 접근 시
|
|
500 에러가 나던 것을 해결 ([hooks.server.js](website/src/hooks.server.js), [+layout.server.ts](website/src/routes/+layout.server.ts))
|
|
- `trailingSlash`를 `'always'`로 변경 — Synology Web Station 같은 일반 정적 서버에서 `/app`, `/help/*` 등의 경로가
|
|
403/404 나던 문제 해결 ([+layout.ts](website/src/routes/+layout.ts))
|
|
- 앱 내부 메뉴의 "도움말" 링크가 상대경로(`./help`)라 위 변경과 충돌하던 것을 절대경로로 수정 ([Menu.svelte](website/src/lib/components/Menu.svelte))
|
|
- `getElevation()`이 CORS로 막힌 고도 타일 요청 실패 시 예외를 그대로 던져서 포인트 이동 작업 전체가 실패하던 문제 수정 —
|
|
실패 시 조용히 폴백하도록 변경 ([utils.ts](website/src/lib/utils.ts))
|
|
- 라우팅 끄고 포인트 이동 시(직선 재연결), 새로 생기는 구간의 고도를 매번 네트워크로 조회하던 것을 개선 —
|
|
양쪽 앵커에 이미 있는 실제 고도값을 거리 비례로 보간하도록 변경. 양쪽 다 알면 보간, 한쪽만 알면 그 값으로 확장,
|
|
둘 다 모르면 그때만 `getElevation()` 폴백(그마저 실패하면 0)
|
|
([routing.ts](website/src/lib/components/toolbar/tools/routing/routing.ts))
|
|
- 내보내기(Export) 다이얼로그의 CSS 클래스 충돌(`relative`+`fixed`)로 다이얼로그가 화면 하단에 잘려서 뜨던 문제 수정 (현재는 다이얼로그 자체를 제거함, 아래 참고)
|
|
|
|
### 변경/제거
|
|
- **내보내기 후원 안내 다이얼로그 제거** — `Export...`/`Export all...`/`Ctrl+S`가 이제 팝업 없이 원본 파일명 그대로 바로 다운로드됨
|
|
(`Export.svelte` 삭제, [Menu.svelte](website/src/lib/components/Menu.svelte)에서 직접 호출)
|
|
- 도메인 관련 하드코딩 문자열을 `gpx.dodo-lab.kr`로 변경 (OG/canonical 메타태그, `sitemap.xml`, PWA manifest, `robots.txt`)
|
|
|
|
## 자체 호스팅 시 알아둘 점 (CORS 제약)
|
|
|
|
`styles.gpx.studio` / `tiles.gpx.studio` / `overpass.gpx.studio`는 gpx.studio 팀이 직접 운영하는 서버로,
|
|
**`https://gpx.studio` 도메인에서 오는 요청만 허용**하도록 CORS가 설정되어 있습니다. 따라서 이 도메인 밖에서 자체 호스팅하면:
|
|
|
|
- 지도 스타일 4종(Liberty Topo, Liberty Satellite, OSM, OSM Topo)이 로드되지 않고, **자동으로 순정 OpenStreetMap 타일로 대체**됩니다(코드 수정 없이 정상 동작).
|
|
- 3D 지형(Mapterhorn), 고도 데이터 조회, 관심 지점(POI) 오버레이 레이어는 사용할 수 없습니다.
|
|
- 라우팅(GraphHopper `graphhopper.gpx.studio`, BRouter `brouter.de`)은 CORS가 열려 있어 정상 동작합니다.
|
|
|
|
## 개발 환경
|
|
|
|
원본과 동일하게 두 부분으로 나뉩니다:
|
|
|
|
- `gpx`: GPX 파일 파싱/조작용 TypeScript 라이브러리
|
|
- `website`: [SvelteKit](https://kit.svelte.dev/) 기반 웹앱
|
|
|
|
**Node.js 22 이상**이 필요합니다 (`website/.npmrc`에 `engine-strict=true`가 설정되어 있고,
|
|
일부 의존성이 Node 22+를 요구합니다).
|
|
|
|
### `gpx` 라이브러리 빌드
|
|
|
|
```bash
|
|
cd gpx
|
|
npm install
|
|
npm run build
|
|
```
|
|
|
|
### `website` 개발 서버 실행
|
|
|
|
지도를 표시하려면 [MapTiler 키](https://cloud.maptiler.com/auth/widget?next=https://cloud.maptiler.com/maps/)가 필요합니다.
|
|
`website/.env` 파일에 저장하세요.
|
|
|
|
```bash
|
|
cd website
|
|
echo PUBLIC_MAPTILER_KEY={YOUR_MAPTILER_KEY} >> .env
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
> 개발 서버(`npm run dev`)는 메모리를 많이 씁니다(테스트 시 약 800MB). 상시 배포에는 쓰지 마세요.
|
|
|
|
### 정적 배포용 빌드
|
|
|
|
```bash
|
|
cd website
|
|
npm run build
|
|
```
|
|
|
|
`website/build/`에 순수 정적 파일(HTML/CSS/JS)이 생성됩니다(테스트 시 약 34MB). Node.js 런타임 없이
|
|
nginx, Apache, Synology Web Station 등 아무 정적 파일 서버에 그대로 올리면 됩니다.
|
|
|
|
## 원본 프로젝트 정보
|
|
|
|
이 프로젝트는 다음 오픈소스 프로젝트들 덕분에 가능했습니다 (원본 [README](https://github.com/gpxstudio/gpx.studio/blob/main/README.md) 참고):
|
|
|
|
- 개발: [Svelte](https://github.com/sveltejs/svelte) / [SvelteKit](https://github.com/sveltejs/kit), [MDsveX](https://github.com/pngwn/MDsveX)
|
|
- 디자인: [shadcn-svelte](https://github.com/huntabyte/shadcn-svelte), [@lucide/svelte](https://github.com/lucide-icons/lucide/tree/main/packages/svelte), [tailwindcss](https://github.com/tailwindlabs/tailwindcss), [Chart.js](https://github.com/chartjs/Chart.js)
|
|
- 로직: [immer](https://github.com/immerjs/immer), [Dexie.js](https://github.com/dexie/Dexie.js), [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser), [SortableJS](https://github.com/SortableJS/Sortable)
|
|
- 지도: [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js), [GraphHopper](https://github.com/graphhopper/graphhopper), [OpenStreetMap](https://www.openstreetmap.org), [Mapterhorn](https://github.com/mapterhorn/mapterhorn)
|
|
- 검색: [DocSearch](https://github.com/algolia/docsearch)
|
|
|
|
## 라이선스
|
|
|
|
원본과 동일하게 MIT 라이선스입니다 — [LICENSE](LICENSE) 참고.
|