위치 기반 서비스는 배달, 택시, SNS 등 많은 앱의 핵심 기능입니다. 권한 처리부터 실시간 추적까지 정리합니다.


expo-location

BASH
npx expo install expo-location
TSX
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

BASH
npm install react-native-maps
# Expo: npx expo install react-native-maps
TSX
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>
  );
}

두 지점 간 거리 계산

TSX
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 로 지도 표시, 마커, 오버레이를 구현합니다
  • 위치 권한은 포그라운드와 백그라운드 를 구분하여 요청해야 합니다
  • 배터리 소모를 줄이려면 distanceIntervaltimeInterval을 적절히 설정하세요
댓글 로딩 중...