매번 똑같은 코스가 지겹지만 새 코스를 짜기는 번거로운 러너를 위한 앱입니다. 따뜻한 에디토리얼 감성의 모바일 우선 UI에서 코스를 추천받고, 직접 만들고, 러너들과 공유할 수 있습니다.
앱을 열면 바로 지도가 뜹니다. 이 앱이 무엇을 하는 앱인지를 첫 화면이 그대로 보여줍니다: 원하는 거리·스타일로, 실제 뛸 수 있는 코스를 즉시 만들어 준다. 상단에 오늘의 러닝 컨디션(기온·미세먼지·적합도)이 한 줄로 붙어 뛸지 말지 바로 판단할 수 있습니다.
지도가 화면 전체를 차지하고, 입력·결과는 그 위에 떠 있는 카드로 올라갑니다.
- 상단 떠 있는 입력 카드(모드 전환 · 출발/목표 행 · 데이터 소스 뱃지)
- 지도 위 거리 슬라이더 pill, 우측 원형 버튼(내 위치 · 되돌리기)
- 접히는 바텀시트 — 손잡이를 눌러 접으면 지도가 넓게 보임
- 선택한 코스는 경사 색상 실선, 나머지 후보는 흐린 점선으로 함께 표시해 한눈에 비교
- 결과는 문장형 헤드라인으로: “누적 상승
47m→ 34m 로 줄였어요” - 비교 카드: 지도의 선 스타일과 1:1 대응하는 스와치 + 상승 뱃지 + 우측 매칭 점수
러너가 직접 코스를 짜는 두 가지 방식:
- 핀으로 만들기 — 지도에 가고 싶은 지점을 핀으로 찍고 러닝 스타일을 고르면, 여러 경로 후보를 생성해 스타일에 가장 맞는 코스를 추천. 시작점 복귀(순환) / 편도를 선택할 수 있습니다.
- 거리로 만들기 — 시작점(내 위치)과 목표 거리를 정하면 왕복 루프 또는 편도(네 방향 후보: 북/동/남/서쪽 방면)를 생성해 스타일 매칭이 높은 순으로 추천
두 모드 모두 사람이 실제로 걷고 뛸 수 있는 보행 경로를 따라갑니다. 경로는 보도·공원길· 산책로에 스냅되며, 구간별 경사(고도)를 계산해 경사 색상(급내리막·내리막·평지·오르막· 급오르막)으로 지도에 표시합니다. 러닝 스타일은 평지 / 완만 / 오르막내리막 / 경사 훈련 중 선택.
경로는 이 순서로 만들어집니다 — 키가 없어도 실제 보행로가 나옵니다.
| 우선순위 | 소스 | 키 | 내용 |
|---|---|---|---|
| 1 | OpenRouteService | 필요 | 도보 경로 + 왕복 생성 + 고도를 한 번에 |
| 2 | OSRM foot (FOSSGIS 공개 서버) | 불필요 | 실제 보행로 경로. 고도는 Open-Meteo Elevation 으로 조회 |
| 3 | 데모(직선) | — | 위 둘 다 실패할 때만. 실제 도로가 아니며 화면에 |
상단 뱃지가 지금 무엇으로 그렸는지 그대로 보여줍니다(🚶 실보행로 · OSM / 🛰 실경로 · ORS /
⚠️ 직선 데모). 거리 모드의 왕복 루프는 실제 도로로 이어 붙인 뒤 실측 거리로 반지름을
보정해 목표 거리에 수렴시킵니다.
베이스맵은 연회색 톤(CARTO Positron / Mapbox Light, 카카오맵은 타일 채도만 낮춤)을 써서 지도는 배경으로 물러나고 컬러 경로가 주인공이 되도록 했습니다.
- 브라우저 GPS(
watchPosition)로 거리·시간·평균/현재 페이스를 실시간 기록 - 라이브 트랙 지도(현재 위치를 따라가며 지나온 경로 표시), 일시정지/재개/종료
- 뛰는 동안 화면 꺼짐 방지(Screen Wake Lock, 탭 복귀 시 자동 재획득)
- 종료 후 요약(거리·시간·페이스·경사 고도)에서 바로 저장·공유·내보내기
- GPS를 쓸 수 없는 환경(데스크톱 등)에서는 데모 재생으로 체험 가능
- 홈의 "지금 바로 뛰기" 또는 만든 코스의 "이 코스로 뛰기"로 진입
- 배포 주소를 폰에서 열고 홈 화면에 추가하면 앱처럼 실행됩니다(주소창 없는 standalone)
- Android/Chrome 은 설치 버튼, iOS Safari 는 공유 → "홈 화면에 추가" 안내 배너 제공
- 서비스 워커가 앱 셸을 캐시해 오프라인에서도 실행(지도 타일·실시간 API는 네트워크 필요)
- 만든 코스·기록한 러닝을 내 코스로 저장 → 저장 탭에서 다시 열기
- 공유 링크: 경로를 polyline 으로 압축해 URL 로 공유(백엔드 불필요). 링크로 들어오면 코스가 그대로 열립니다. Web Share API / 클립보드 복사 지원
- 어떤 코스/기록이든 GPX 파일로 내보내기 → Strava·가민 커넥트 등에 업로드
- "Strava에 올리기": 기본은 GPX 저장 + Strava 업로드 페이지 열기(연결 없이 바로 동작)
- (선택)
server/strava-worker를 배포하고 주소를 넣으면 버튼 한 번에 자동 업로드 — OAuth 토큰 교환·업로드 중계를 Cloudflare Worker 가 처리 (아래 배포 문서 참고)
- 러닝을 마치면 자동으로 내 코스에 저장되고, 마이의 모든 숫자가 여기서 계산됩니다 (이번 주 거리·요일 막대·누적·연속 일수·러닝 횟수·배지). 샘플 숫자 없음 — 기록이 없으면 정직한 빈 상태를 보여줍니다.
- 주간 목표(± 조절), 러닝화 등록제 — 등록한 날 이후의 실제 기록 거리로 마일리지 누적
- 페이스 계산기(5K·10K·하프 예상 기록) — 코스별 예상 시간에도 반영
- 계정 동기화(이메일 로그인) — 기록·설정이 계정에 자동 백업, 기기를 바꿔도 유지
- 파일 백업 — 로그인 없이 쓰는 안전망 (JSON 내보내기/가져오기)
국내외 러닝 앱/커뮤니티 자료를 분석해 자주 뛰는 러너가 실제로 원하는 요소를 담았습니다: 페이스·예상 시간, 구간 경사·고도, 날씨·미세먼지·복장 추천, 급수·화장실·야간 조명 안전, 노면, 코스 다양성, 러닝화 마일리지, 러닝 계산기, 크루·공유·함께 달리기 등.
모든 키는 선택 사항입니다. 키가 하나도 없어도 실제 보행 경로·실제 고도로 동작합니다
(OSRM foot + Open-Meteo, 둘 다 키 불필요). 키를 넣으면 더 정확한 소스로 전환됩니다.
연결 방법은 두 가지 — .env(.env.example 참고) 또는 앱 실행 후
마이 페이지 → 외부 서비스 연동에 붙여넣기.
| 서비스 | 역할 | 없을 때 | 발급 |
|---|---|---|---|
| 카카오맵 JS 키 | 기본 지도(한국) | OpenStreetMap 폴백 | developers.kakao.com |
| 카카오맵 링크 | 길찾기·로드뷰 열기 | — (키 불필요, 항상 동작) | 없음 |
| OpenRouteService | 도보 경로·경사 (선택, 더 정확) | OSRM 도보 경로로 자동 대체 | openrouteservice.org |
| OSRM foot · Open-Meteo | 실제 보행 경로 + 고도 | — (키 불필요, 기본값) | 없음 |
| Mapbox | 카카오 대신 쓸 지도(선택) | 미사용 | account.mapbox.com |
| Strava Worker | 자동 업로드(선택) | GPX 수동 업로드 | server/strava-worker |
- 카카오맵을 기본 지도로 씁니다(국내 대상). 지도 계층은 스위처블 —
카카오 JS SDK 를 불러올 수 있으면 카카오맵, 아니면 자동으로 Leaflet/OSM(또는 Mapbox)으로
폴백합니다. 카카오는 자체 JS SDK 라 SDK 를 못 부르는 환경에서도 앱이 안 깨집니다.
⚠️ 카카오맵이 뜨려면 개발자 콘솔 → Web 플랫폼에 실행/배포 도메인을 등록해야 합니다 (http://localhost:5173, 배포 주소 등). - 도보 경로·고도는 카카오와 무관하게 OpenRouteService 또는 OSRM foot으로 계산하고, 그 좌표를 지도 위에 경사 색상 폴리라인으로 그립니다(카카오는 지도 표시 담당).
- 카카오맵 링크(
map.kakao.com/link/...)는 API 키가 필요 없습니다. 도메인 등록이나 키 상태와 무관하게 항상 동작하므로, 코스 상세·경로 시트에서 출발점까지 길찾기 · 지도 보기 · 로드뷰를 카카오맵 앱/웹으로 바로 넘겨줍니다 (실제 내비게이션은 카카오맵에 맡기는 편이 정확합니다). - Strava 자동 업로드는
client_secret을 브라우저에 둘 수 없어 중계 서버가 필요합니다. 바로 배포할 수 있는 Cloudflare Worker 를server/strava-worker에 포함해 두었습니다(무료·단일 파일, 5분 배포). 배포 전에도 GPX 내보내기 → Strava 수동 업로드는 그대로 동작합니다.
.github/workflows/deploy.yml 이 푸시 시 자동으로 빌드→Pages 배포합니다.
- 저장소 Settings → Pages → Build and deployment → Source: GitHub Actions 선택(최초 1회)
- 이 브랜치(또는 main)로 push → Actions 가 빌드/배포 →
https://<owner>.github.io/<repo>/생성 - 그 주소를 카카오 개발자 콘솔 → Web 플랫폼 도메인에 등록하면 카카오맵이 표시됩니다
(예:
https://won-topiaa.github.io)
vite.config.ts의base: './'로 하위 경로에서도 에셋이 정상 로드됩니다. 별도 배포 비밀키는 필요 없습니다(지도 키는 도메인 제한 공개 키).
- React 18 + TypeScript + Vite
- Tailwind CSS (따뜻한 에디토리얼 디자인 시스템) + lucide-react 아이콘
- 카카오맵 JS SDK(기본) ↔ Leaflet / react-leaflet(폴백, OSM·Mapbox 타일) 스위처블 지도
- OpenRouteService(키 필요) ↔ OSRM foot(키 불필요) 도보 라우팅 + 데모 폴백
- Open-Meteo (날씨 · 대기질 · 고도, 키 불필요)
- Geolocation API 실시간 기록 · GPX 1.1 내보내기 · Encoded Polyline 공유 링크
- 차트는 외부 의존성 없는 순수 SVG
npm install
npm run dev # 개발 서버 (http://localhost:5173)
npm run build # 타입체크 + 프로덕션 빌드
npm run preview # 빌드 결과 미리보기
npm run check # 로직 검증 3종 (GPS 필터 · 지역 기능 · 나가는 결과물)
npm run check:smoke # 빌드된 dist 를 실제 브라우저로 열어 전 화면 클릭 (배포 직전)
npm run check:scenario # 다양한 실패 상황 연출 — 오프라인·위치거부·API차단·손상 저장소·공유링크 변조 등
npm run check:live # 실제 ORS·Overpass 호출 검증 (느리고 외부 사정을 탄다)src/
├─ lib/ # 도메인 로직 (UI와 무관)
│ ├─ types.ts # 코스·선호·추천 타입
│ ├─ scoring.ts # 취향 가중치 추천 엔진
│ ├─ geo.ts # 거리·방위·경로 생성 등 지오 계산
│ ├─ routing.ts # ORS·OSRM(도보)·데모 provider, 구간 경사 계산
│ ├─ elevation.ts # Open-Meteo 실제 고도 조회(샘플링 + 보간)
│ ├─ routeStyle.ts # 러닝 스타일 점수화 + 경사 색상 밴드
│ ├─ courseBuilder.ts # 후보 경로 생성 → 스타일/거리 랭킹
│ ├─ weather.ts # 날씨·미세먼지·러닝 적합도
│ ├─ format.ts # 페이스·시간·거리 포맷
│ ├─ config.ts # 설정(키·페이스·위치) 지속
│ ├─ scene.ts # 코스 → 감성 씬 매핑
│ ├─ polyline.ts # Encoded Polyline + 공유 링크 코덱
│ ├─ savedRoutes.ts # 만든/기록한 코스 저장 + 공유 복원
│ ├─ gpx.ts # GPX 1.1 생성/다운로드
│ ├─ strava.ts # Strava OAuth authorize URL
│ ├─ useRunRecorder.ts # 실시간 GPS 기록 훅(+데모 폴백)
│ ├─ kakaoLoader.ts # 카카오맵 SDK 동적 로더
│ ├─ useKakao.ts # 카카오 로드 상태 훅(폴백 신호)
│ ├─ routeColor.ts # 경사 색상 폴리라인 그룹(지도 공용)
│ ├─ wakeLock.ts # 러닝 중 화면 꺼짐 방지
│ └─ registerSW.ts # 서비스 워커 등록(프로덕션)
├─ server/strava-worker/ # Strava 자동 업로드 Cloudflare Worker (선택 배포)
├─ server/supabase/ # 이메일 로그인 동기화 설정 가이드 (Supabase)
├─ public/ # manifest·서비스워커·앱 아이콘(PWA)
├─ data/
│ └─ courses.ts # 서울 실제 코스 큐레이션 (14곳)
├─ components/ # 지도 스위처(RouteMap/PathMap/LiveMap) + 카카오/Leaflet
│ # 구현·차트·카드·시트(CourseDetail/RouteSheet)·기록·네비
├─ screens/ # Build(홈) / Explore(추천) / Saved / My
└─ App.tsx # 화면 라우팅 · 전역 상태 · 공유 링크 수신
- 서울 코스의 GPS 경로 좌표는 실제 권역을 따라 단순화한 값이며, 6요소 속성/커뮤니티 피드/마이 페이지 통계는 큐레이션·샘플 데이터입니다. 실제 서비스에서는 지자체 DEM·POI, 실제 사용자 데이터로 대체됩니다.
- 향후: 카카오/네이버 지도 연동, 실시간 GPS 기록, 스트라바 연동 취향 학습, 크루/챌린지.