본문으로 건너뛰기
Back to Projects
졸업작품 (FE 1 / BE 2)

Runner's High

러너가 지도로 코스를 고르고 GPS로 달리기를 기록하며 다른 참가자와 위치를 공유하는 모바일 앱입니다.

2025.02 - 2025.07 · Frontend / Mobile (전담)

TypeScriptReact NativeExpoZustand
사용자
혼자 또는 그룹으로 달리기를 기록하는 러너
해결 과제
러너가 지도에서 코스를 고르고, 러닝 방식에 맞춰 위치와 기록을 보며 달릴 수 있는 모바일 화면이 필요했습니다.
내 기여
FE 1명·BE 2명 졸업작품 팀에서 모바일 프론트엔드를 전담해 코스 탐색, 러닝 모드별 화면·상태, 실시간 위치 전송·구독 흐름을 구현했습니다.
기술 선택 이유
코스·기록처럼 서버에서 받는 데이터는 TanStack Query로, 위치·러닝 모드처럼 앱에서 바뀌는 상태는 Zustand와 모드별 훅으로 나눴습니다.
결과
지도에서 코스를 찾아 선택하고, 개인·그룹 러닝 중 위치와 진행 상태를 볼 수 있는 앱 흐름을 구현했습니다.
User flow

서비스 이용 흐름

  1. 01

    지도에서 코스 선택

  2. 02

    러닝 모드 시작

  3. 03

    위치·기록 확인

  4. 04

    종료 후 기록 확인

Case studies

문제 해결

01

연결이 돌아와도 참가자 위치가 갱신되지 않음

문제
  • 러닝 중에는 Wi-Fi와 모바일 데이터 전환이나 일시적인 음영 지역 때문에 WebSocket이 끊길 수 있습니다. 연결만 다시 맺어도 이전에 보고 있던 위치 topic 구독은 사라지므로, 화면상으로는 달리기가 계속돼도 참가자 위치가 더 이상 갱신되지 않을 수 있었습니다.
해결
  • STOMP client에 heartbeatIncoming, heartbeatOutgoing을 설정해 연결 이상을 감지하고, reconnectDelay로 자동 재접속하게 했습니다.
  • 재접속이 끝나면 현재 활성화된 러닝 모드가 필요한 topic을 다시 구독하도록 연결 생명주기와 화면 생명주기를 분리했습니다. 그룹 러닝의 위치 공유와 개인 러닝의 기록 경로도 따로 두어 불필요한 전송을 막았습니다.
02

위치 갱신이 다른 러닝 화면까지 다시 그리게 함

문제
  • 달리는 동안 GPS 위치는 계속 바뀌고, 사용자는 개인·그룹·코스 러닝을 오갈 수 있습니다. 위치, 코스, 인증, 러닝 진행 상태를 한곳에서 관리하면 작은 변경에도 관련 없는 화면과 통신 로직까지 함께 반응했습니다.
해결
  • 위치, 러닝, 코스, 인증 상태를 Zustand store 단위로 나누고 각 화면이 필요한 상태만 구독하도록 구성했습니다.
  • 개인·그룹·코스 러닝은 모드별 훅으로 분리했습니다. 각 모드가 필요한 STOMP publish/subscribe 경로만 열도록 해 화면 조건문과 실시간 통신 책임이 한 컴포넌트에 쌓이지 않게 했습니다.
기술 설계 더 보기처리 흐름 · 기술 선택 · 대안
01

기술 선택과 이유

  • WebSocket(STOMP): 실시간 위치 publish/subscribe 경로를 명시적으로 분리하기 쉬워 선택했습니다.
  • expo-location: foreground/background 위치 추적과 옵션 제어가 필요해서 사용했습니다.
  • Zustand: 위치, 코스, 인증, 러닝 상태를 store별로 분리하기 위해 사용했습니다.
  • TanStack Query: 코스와 기록 조회처럼 서버가 원본인 데이터만 담당하게 했습니다.
02

고려한 대안과 Trade-off

  • 모바일 위치 정확도는 기기와 OS 정책의 영향을 받기 때문에 계산 로직만으로 모든 흔들림을 제거할 수는 없습니다.
  • 실시간 위치 공유는 네트워크 품질에 의존하므로 heartbeat와 reconnect로 복구 경로를 두는 데 집중했습니다.
  • 운영 사용자 수, 연결 성공률, GPS 정확도 개선률은 확인되지 않아 성과 수치로 사용하지 않았습니다.