러닝과 걷기를 짧은 간격으로 반복하며, 무리하지 않고 꾸준히 운동하기 위한 인터벌 러닝 웹 앱입니다.
- Demo: Interval Runner
- Repository: 1005jh/interval-runner
건강을 위해 하루 8~9km씩 러닝을 하면서 기록이 줄고 더 오래 뛸 수 있는 변화가 눈에 보이자, 운동 강도를 빠르게 높이게 되었습니다. 결국 슬개건염으로 약 한 달간 치료와 회복이 필요했고, 러닝을 처음 시작하거나 재개할 때는 작은 단위의 운동과 회복을 반복하는 인터벌 방식이 더 적합하다는 점을 알게 되었습니다.
Interval Runner는 이 경험에서 출발했습니다. 사용자가 러닝 시간과 걷기 시간을 직접 설정하고, 현재 페이스에 맞춰 안전하게 운동을 이어갈 수 있도록 타이머, 알림음, 위치 기반 기록을 한 화면에 모았습니다.
- 러닝/걷기 인터벌 시간 설정
- 현재 페이즈에 따라 색상이 바뀌는 카운트다운 타이머
- 시작, 일시정지, 재개, 정지 컨트롤
- 러닝/걷기 전환 시 Web Audio API 기반 알림음 제공
- Geolocation API로 이동 좌표 수집
- Kakao Maps API로 현재 위치와 이동 경로 표시
- Haversine 공식 기반 누적 거리 계산
- 총 거리, 총 운동 시간, 평균 페이스 요약
- 모바일 화면을 기준으로 한 다크 UI
| Area | Tech |
|---|---|
| Frontend | React, TypeScript |
| Styling | styled-components |
| State | Zustand |
| Location | Geolocation API, Kakao Maps API |
| Audio | Web Audio API |
| Build | Create React App |
| Deploy | Vercel |
zustand 스토어에서 운동 활성화 여부, 일시정지 상태, 현재 페이즈, 경과 시간, 위치 좌표, 누적 거리를 관리합니다. 타이머 로직은 useTimer 훅으로 분리해 1초마다 상태를 갱신하고, 설정된 러닝/걷기 시간이 끝나면 다음 페이즈로 전환합니다.
useGeolocation 훅에서 navigator.geolocation.watchPosition을 사용해 운동 중 위치를 추적합니다. 수집된 좌표는 전역 상태에 저장하고, 좌표 배열이 바뀔 때마다 누적 거리를 다시 계산합니다.
두 좌표 사이의 거리는 Haversine 공식으로 계산합니다. GPS 좌표 배열을 순회하면서 각 구간 거리를 더해 전체 이동 거리를 구하고, 이를 기반으로 평균 페이스를 표시합니다.
Kakao Maps SDK를 동적으로 로드한 뒤 현재 위치를 중심으로 지도를 초기화합니다. 운동 중 좌표가 쌓이면 폴리라인과 현재 위치 마커를 갱신해 사용자가 자신의 이동 경로를 확인할 수 있도록 구성했습니다.
npm install프로젝트 루트에 .env 파일을 만들고 Kakao Maps JavaScript 키를 설정합니다.
REACT_APP_KAKAO_MAP_KEY=your_kakao_map_keynpm startnpm run buildsrc
├── components
│ ├── Map
│ ├── Settings
│ ├── Stats
│ └── Timer
├── hooks
│ ├── useAudio.ts
│ ├── useGeolocation.ts
│ └── useTimer.ts
├── stores
│ └── trainingStore.ts
├── types
└── utils



