[토이] 런플립 개발 일지 2

2해승·2023년 8월 7일
0

런플립 개발 일지

목록 보기
2/5
post-thumbnail

오늘은 런플립의 가장 중요한 페이지인 운동시작 스크린의 개발 내용을 담아보려한다. 스톱 워치가 시작됨과 동시에 사용자가 현재 위치에서 이동한 경로를 PolyLine으로 제공하고 운동 결과 데이터를 산출하여 EndScreen.js 으로 포워딩 하였다.

개발 진행 내용

  • 컴포넌트 분할

<Map.js>
위치정보 권한 요청 및 현재 위치 불러오기
스톱 워치의 Start-Stop 상태 값으로 현재 상태 반영하기(달리기)

<ControlPanel.js>
스톱 워치 및 handleStart & Stop
이동 거리 실시간 업데이트
운동 결과 데이터 포워딩

  • Google maps API 연동 및 현재 위치 불러오기
  • StopWatch
  • 경로 데이터 받아와서 PolyLine 그리기
  • 운동 결과 데이터 (경과 시간, 전체 거리, 경로)

Google maps API 연동 및 현재 위치 불러오기

여러 Map API 중 구글을 선택한 이유는 리액트 네이티브 expo와 연동이 간편하고 공식 문서에서 라이브러리 가이드라인을 제공하기 때문이다.

import MapView, { PROVIDER_GOOGLE, Polyline } from "react-native-maps";
import * as Location from 'expo-location'

expo-location의 경우 현재 좌표값을 받아올 뿐만 아니라 위치 정보 제공 동의에 관한 권한도 가져올 수 있다.

위치 정보 제공 동의가 된다면 현재 위치를 초기화 하여 사용자의 위치를 정확하게 제공할 수 있도록 하였다.


StopWatch

https://www.npmjs.com/package/react-native-stopwatch-timer

스톱 워치는 시간을 제어하는 기본적인 기능 뿐만 아니라 사용자가 러닝을 하고있는지의 여부도 결정한다. 스톱 워치의 시작-일시정지-종료 버튼에 따라 Map.js에서 사용자의 위치 폴리라인을 제공할 수 있기 때문이다.

//StartScreen.js

const [isRunning, setIsRunning] = useState(false)

그러기 위해선 StopWatch의 state값이 Map.js 컴포넌트와 공유되어야 한다.
상위 StartScreen.js에서 isRunning state를 생성하여 콜백 함수를 통해 스톱 워치 동작에 따라 러닝 상태값이 반영되게 했다.

(스톱위치 동작하는거 움짤로 만들기?)

경로 데이터 받아와서 PolyLine 그리기

이 기능은 가장 애먹은 기능이 아닐까 한다.
폴리 라인은 사용자가 이동하는 좌표 값이 배열로 쌓이고 해당 데이터들이 지도 상의 점으로 인식되어 선을 이어서 시각적으로 제공하는 것이다.

1. 위치 정보가 변경될 때 호출하는 콜백 함수
변경된 위치 정보를 가져와 'setCoordinates'를 통해 좌표 업데이트

const handleLocationChange = (location) => {
            if(isRunning) {
                const {longitude, latitude} = location.coords
                setCoordinates((prevCoordinates) => [...prevCoordinates, {longitude, latitude}])
            }
}

2. 위치 정보 구독 함수
'Location.watchPositionAsync'를 사용하여 위치 정보를 구독하고, 위치 정보가 변경될 때 마다 'handleLocationChange' 함수 호출

const startLocationSubscription = async () => {
            const subscription = await Location.watchPositionAsync(
                { accuracy: Location.Accuracy.High, distanceInterval: 1 },
                handleLocationChange
            )
            setLocationSubscription(subscription)
}

3. locationSubscription.remove() 위치 구독 중지


운동 결과 데이터 (경과 시간, 전체 거리, 경로)

종료 버튼을 클릭하게 되면 아래처럼 안내창이 나오게 되면서 모든 데이터 수집이 멈추게 된다. 이때의 데이터를 운동 결과 스크린으로 보내 칼로리, 페이스 등의 데이터를 계산한다.

거리를 계산하는 것은 haversine 패키지를 이용하여 손쉽게 구현했다.


특이 사항

const [locationSubscription, setLocationSubscription] = useState(null)
.
.
setLocationSubscription(subscription) // 2. 위치 정보 구독 함수에서의 subscription
.
.
locationSubscription.remove()

'locationSubscription' 위치 정보를 감지하기 위해 사용되는 구독을 나타내는 변수로 Location.watchPositionAsync를 호출할 때 반환되는 구독 객체이다.

구독 객체에는 remove라는 메서드가 있어 호출할 경우 해당 구독이 중지되고, 위치 정보 변경을 감지하지 않기 때문에 운동을 마치기 위해 꼭 필요한 기능이라고 볼 수 있다.

개발 중 가장 애먹은 부분이 바로 이 부분이다. 해당 메서드가 동작하지 않아 운동을 마칠 수 없었다.

'locationSubscription' 변수에 할당 된 값이 'undefined'로 반환된 구독 객체가 정상적으로 할당되지 않은 것이 원인이였다.

만일 'Location.watchPositionAsync' 메서드 호출이 실패하였다면 지도 상에 폴리 라인이 그려지지 않았을 것이다. 하지만 테스트는 정상적으로 동작되고 있어서 비동기적 처리가 필요하다고 확인하였다.

useEffect 내에서 해당 함수를 비동기적으로 처리하여 해결하였다.
(2. 위치 정보 구독 함수 참고)

To-Do List

  • 운동 완료 페이지 제작
  • 상세 기능 : 운동 시작 페이지에서 도출된 데이터 기반으로 칼로리 및 페이스 계산, 운동 완료 경로 제공
  • 로컬 스토리지 및 데이터베이스에 데이터 저장
profile
Node 백엔드 개발자 / 데브옵스 취준생

0개의 댓글