위치정보와 지도 — Geolocation과 MapView
위치 기반 서비스는 배달, 택시, SNS 등 많은 앱의 핵심 기능입니다. 권한 처리부터 실시간 추적까지 정리합니다.
expo-location
npx expo install expo-location
import * as Location from 'expo-location';
// 현재 위치 가져오기
async function getCurrentLocation() {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
Alert.alert('위치 접근 권한이 필요합니다');
return null;
}
const location = await Location.getCurrentPositionAsync({
accuracy: Location.Accuracy.High,
});
return {
latitude: location.coords.latitude,
longitude: location.coords.longitude,
};
}
// 위치 실시간 추적
function useLocationTracking() {
const [location, setLocation] = useState(null);
useEffect(() => {
let subscription: Location.LocationSubscription;
(async () => {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') return;
subscription = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.High,
distanceInterval: 10, // 10m 이동마다 업데이트
timeInterval: 5000, // 5초마다 업데이트
},
(newLocation) => {
setLocation(newLocation.coords);
}
);
})();
return () => subscription?.remove();
}, []);
return location;
}
// 주소 → 좌표 변환 (지오코딩)
async function geocode(address: string) {
const results = await Location.geocodeAsync(address);
if (results.length > 0) {
return { latitude: results[0].latitude, longitude: results[0].longitude };
}
return null;
}
// 좌표 → 주소 변환 (역지오코딩)
async function reverseGeocode(latitude: number, longitude: number) {
const results = await Location.reverseGeocodeAsync({ latitude, longitude });
if (results.length > 0) {
const addr = results[0];
return `${addr.city} ${addr.district} ${addr.street}`;
}
return null;
}
react-native-maps
npm install react-native-maps
# Expo: npx expo install react-native-maps
import MapView, { Marker, Callout, PROVIDER_GOOGLE } from 'react-native-maps';
function MapScreen() {
const [region, setRegion] = useState({
latitude: 37.5665,
longitude: 126.978,
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});
const markers = [
{ id: '1', latitude: 37.5665, longitude: 126.978, title: '서울시청' },
{ id: '2', latitude: 37.5796, longitude: 126.977, title: '경복궁' },
];
return (
<MapView
style={{ flex: 1 }}
provider={PROVIDER_GOOGLE}
region={region}
onRegionChangeComplete={setRegion}
showsUserLocation // 현재 위치 표시
showsMyLocationButton // 현재 위치 버튼
>
{markers.map((marker) => (
<Marker
key={marker.id}
coordinate={{ latitude: marker.latitude, longitude: marker.longitude }}
title={marker.title}
>
<Callout>
<View style={{ padding: 8 }}>
<Text style={{ fontWeight: 'bold' }}>{marker.title}</Text>
</View>
</Callout>
</Marker>
))}
</MapView>
);
}
두 지점 간 거리 계산
function getDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
const R = 6371; // 지구 반지름 (km)
const dLat = ((lat2 - lat1) * Math.PI) / 180;
const dLon = ((lon2 - lon1) * Math.PI) / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; // km
}
정리
- expo-location 으로 위치 권한 요청, 현재 위치, 실시간 추적을 처리합니다
- react-native-maps 로 지도 표시, 마커, 오버레이를 구현합니다
- 위치 권한은 포그라운드와 백그라운드 를 구분하여 요청해야 합니다
- 배터리 소모를 줄이려면
distanceInterval과timeInterval을 적절히 설정하세요
댓글 로딩 중...