![[React Native] react-native-geolocation-service 라이브러리를 사용해보자 [React Native] react-native-geolocation-service 라이브러리를 사용해보자](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
개요
프로젝트를 진행하면서 위치 서비스를 사용하는 일이 생겼고 자연스럽게 Geofence에 대해 알게 되었다.
Geofence의 개념과 라이브러리에 대해 관심이 생겼고 간단한 프로젝트를 구현해보려고 한다.
Geofence
Geofence란 지리(Geography)와 울타리(Fence)를 결합한 것이다.
쉽게 말하자면 특정 위치로부터 반경 x미터의 가상 구역을 만드는 것을 의미한다.
Geofence를 사용하는 것을 Geofencing이라고 부른다.
Geofence는 위도와 경도를 입력받아 하버사인 공식(Haversine Formula)을 이용해서 가상 구역을 만든다.
하버사인 공식이란?
구면 삼각법에서 지구와 같은 구면의 두 점 사이의 대원 거리를 계산하는 공식
하버사인 공식
하버사인 공식을 구현한 코드는 다음과 같다.
const EARTH_RADIUS = 6371; // 지구 반지름 (km)
const degToRad = (deg: number) => deg * (Math.PI / 180); // 각도를 라디안으로 변환하는 함수
const latitudeDiff = degToRad(latitude - nowLatitude);
const longitudeDiff = degToRad(longitude - nowLongitude);
const sinLatDiff = Math.sin(latitudeDiff / 2) ** 2;
const sinLonDiff = Math.sin(longitudeDiff / 2) ** 2;
const cosNowLat = Math.cos(degToRad(nowLatitude));
const cosLat = Math.cos(degToRad(latitude));
const centralAngle = 2 * Math.atan2(Math.sqrt(sinLatDiff + cosNowLat * cosLat * sinLonDiff), Math.sqrt(1 - sinLatDiff - cosNowLat * cosLat * sinLonDiff));
const distance = Math.round(EARTH_RADIUS * centralAngle * 1000); // 단위를 km에서 m로 변환
위 공식은 이번 프로젝트에서는 사용하진 않을 것이기 때문에 바로 코드를 작성한다.
코드
위치 권한을 얻는 Authority 와 위치를 보여주는 Main 두 개의 스크린으로 작성했다.
사용 라이브러리
> @react-navigation/native
> @react-navigation/native-stack
> react-native-geolocation-service
> react-native-permissions
> react-native-safe-area-context
> react-native-screens
> styled-components
> zustand
Authority.tsx
import React, { useCallback, useEffect } from "react";
import { PermissionsAndroid } from "react-native";
import { AuthorityProps } from "../navigation/navigation";
import { REQUIRE_LOCATION_PERMISSIONS, checkPermissions } from '../utils/permission';
import { Layout, NextButton } from "../utils/styles";
const Authority = ({route, navigation}: AuthorityProps) => {
// 위치 권한 상태 체크
const onLocationPermissionsCheck = useCallback(async () => {
const { result, permission } = await checkPermissions(REQUIRE_LOCATION_PERMISSIONS);
if ( !result && permission ) {
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
)
}
}, []);
useEffect(() => {
onLocationPermissionsCheck();
}, []);
return (
<Layout>
<NextButton
title="Next"
onPress={() => navigation.navigate("Main")}
/>
</Layout>
);
};
export default Authority;
Main.tsx
import React, { useEffect } from "react";
import { SafeAreaView } from "react-native";
import { MainProps } from "../navigation/navigation";
import useGeolocation from "../hooks/useGeolocation";
import useDataStore from "../store/useDataStore";
import { Layout, TextFont } from "../utils/styles";
const Main = ({route, navigation}: MainProps) => {
const { position } = useDataStore();
const { onWatchPosition, onClearWatch } = useGeolocation();
useEffect(() => {
onWatchPosition();
return () => onClearWatch();
}, [position]);
return (
<SafeAreaView>
<Layout>
<TextFont>latitude : {position.latitude}</TextFont>
<TextFont>longitude : {position.longitude}</TextFont>
</Layout>
</SafeAreaView>
);
};
export default Main;
useGeolocation.ts
import { useCallback } from "react";
import GeoLocation from "react-native-geolocation-service";
import useDataStore from "../store/useDataStore";
let watchId = -1;
const getWatchId = () => watchId;
const setWatchId = (id: number) => {
watchId = id;
};
const useGeolocation = () => {
const { position, setPosition } = useDataStore();
const onClearWatch = useCallback(() => {
if( getWatchId() !== -1 ) {
GeoLocation.clearWatch(watchId);
GeoLocation.stopObserving();
}
}, []);
const onWatchPosition = useCallback(() => {
const id = GeoLocation.watchPosition(
(position) => {
const { latitude, longitude } = position.coords;
setPosition({latitude, longitude});
},
(error) => {
console.log(error);
},
{
accuracy: {
android: "high",
},
enableHighAccuracy: true, // 정확한 위치 추적
});
setWatchId(id);
}, []);
return {
onWatchPosition,
onClearWatch,
}
};
export default useGeolocation;
코드 동작 순서
- Authority에서 위치 권한을 받아온다.
- Next 버튼을 터치하면 Main으로 이동해서 useGeolocation의 onWatchPosition() 메소드를 실행한다.
- onWatchPosition() 메소드에서 받은 현재 위치를 상태 관리 라이브러리에 저장한다.
- 저장된 position 값을 Main 화면에 출력한다.
전체 코드
https://github.com/eoqna/geofence_rn
GitHub - eoqna/geofence_rn
Contribute to eoqna/geofence_rn development by creating an account on GitHub....
github.com
테스트 및 동작 확인
![[React Native] react-native-geolocation-service 라이브러리를 사용해보자 - 테스트 및 동작 확인 [React Native] react-native-geolocation-service 라이브러리를 사용해보자 - 테스트 및 동작 확인](https://blog.kakaocdn.net/dn/cdKJVN/btsDGuuy5Xg/OqXP1KFDDinboprOj4wSO1/img.png)
참고 사이트
https://www.npmjs.com/package/react-native-geolocation-service#API
react-native-geolocation-service
React native geolocation service for iOS and android. Latest version: 5.3.1, last published: a year ago. Start using react-native-geolocation-service in your project by running `npm i react-native-geolocation-service`. There are 57 other projects in the np...
www.npmjs.com
ReactNative로 러닝 어플 만들기 - Geolocation으로 사용자 러닝 트래킹하기
react-native-geolocation-service 활용하기...
velog.io
'📱Mobile > React Native' 카테고리의 다른 글
[React Native] 앱 종료 시에도 React Native 코드 실행 (0) | 2023.12.18 |
---|---|
[React Native] iOS BLE Advertising (0) | 2023.11.21 |
[React Native] Android BLE Advertising (0) | 2023.09.14 |
[React Native] Kakao Login 구현하기 (2) | 2023.03.28 |
[React Native] Naver Login 구현하기 (0) | 2023.03.28 |
댓글