Skip to content

Repository files navigation

react-native-geolocation

⚡️ React Native Geolocation library using TurboModule (New Architecture)

고성능 위치 정보 라이브러리로 iOS와 Android에서 완벽하게 동작합니다.

Features

  • ⚡️ TurboModule - React Native New Architecture 지원
  • 🤙 Promise - Callback 대신 Promise 지원
  • 📍 현재 위치 - 한 번의 호출로 현재 위치 가져오기
  • 👁️ 실시간 추적 - 위치 변화를 실시간으로 감지
  • 🎯 정확도 제어 - High accuracy, distance filter 등 세밀한 제어
  • 🔐 권한 관리 - 쉬운 권한 요청 및 상태 확인
  • 📱 Cross Platform - iOS & Android 완벽 지원
  • 🎉 TypeScript - 완전한 타입 지원
  • 🚀 Event Emitter - 실시간 이벤트 기반 업데이트

Installation

npm install react-native-geolocation
# or
yarn add react-native-geolocation

iOS

cd ios && pod install

Info.plist에 권한 설명 추가:

<key>NSLocationWhenInUseUsageDescription</key>
<string>앱이 위치 정보를 사용하기 위해 권한이 필요합니다.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>백그라운드에서도 위치 정보를 사용하기 위해 권한이 필요합니다.</string>

Android

AndroidManifest.xml에 권한 추가 (자동으로 포함됨):

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Usage

기본 사용법

import {
  requestAuthorization,
  getCurrentPosition,
  watchPosition,
  clearWatch,
  addLocationListener,
  type GeolocationPosition,
} from 'react-native-geolocation';

// 1. 권한 요청
const status = await requestAuthorization();
console.log('권한 상태:', status); // 'granted', 'denied', etc.

// 2. 현재 위치 가져오기
const position = await getCurrentPosition({
  enableHighAccuracy: true,
  timeout: 15000,
  maximumAge: 10000,
});

console.log('위도:', position.coords.latitude);
console.log('경도:', position.coords.longitude);
console.log('정확도:', position.coords.accuracy);

실시간 위치 추적

import { useEffect, useState } from 'react';
import {
  watchPosition,
  clearWatch,
  addLocationListener,
  type GeolocationPosition,
} from 'react-native-geolocation';

function App() {
  const [position, setPosition] = useState<GeolocationPosition | null>(null);
  const [watchId, setWatchId] = useState<number | null>(null);

  useEffect(() => {
    // 위치 추적 시작
    const startWatching = async () => {
      const id = await watchPosition({
        enableHighAccuracy: true,
        distanceFilter: 10, // 10m 이동마다 업데이트
      });
      setWatchId(id);
    };

    // 이벤트 리스너 등록
    const subscription = addLocationListener((newPosition) => {
      console.log('위치 업데이트:', newPosition);
      setPosition(newPosition);
    });

    startWatching();

    // 클린업
    return () => {
      if (watchId !== null) {
        clearWatch(watchId);
      }
      subscription.remove();
    };
  }, []);

  return (
    <View>
      <Text>위도: {position?.coords.latitude}</Text>
      <Text>경도: {position?.coords.longitude}</Text>
    </View>
  );
}

API Reference

Methods

requestAuthorization()

위치 권한을 요청합니다.

requestAuthorization(): Promise<string>

Returns:

  • 'granted' - 권한 허용됨 (Android)
  • 'authorizedWhenInUse' - 앱 사용 중 권한 허용 (iOS)
  • 'authorizedAlways' - 항상 권한 허용 (iOS)
  • 'denied' - 권한 거부됨
  • 'notDetermined' - 아직 권한 요청 안 함 (iOS)

Example:

const status = await requestAuthorization();
if (status === 'granted' || status === 'authorizedWhenInUse') {
  // 위치 정보 사용 가능
}

getCurrentPosition(options?)

현재 위치를 한 번 가져옵니다.

getCurrentPosition(options?: GeolocationOptions): Promise<GeolocationPosition>

Parameters:

Name Type Description
options GeolocationOptions 위치 옵션 (optional)

Options:

Property Type Default Description
enableHighAccuracy boolean false GPS 사용 여부 (true: GPS, false: WiFi/Network)
timeout number Infinity 위치 요청 타임아웃 (밀리초)
maximumAge number 0 캐시된 위치의 최대 수명 (밀리초)
distanceFilter number 0 최소 이동 거리 (미터, watchPosition에서 유용)

Returns: Promise<GeolocationPosition>

Example:

const position = await getCurrentPosition({
  enableHighAccuracy: true,
  timeout: 15000,
  maximumAge: 10000,
});

console.log(position.coords.latitude);
console.log(position.coords.longitude);

watchPosition(options?)

위치 변화를 실시간으로 추적합니다.

watchPosition(options?: GeolocationOptions): Promise<number>

Parameters:

Name Type Description
options GeolocationOptions 위치 옵션 (optional)

Options:

Property Type Default Description
enableHighAccuracy boolean false GPS 사용 여부 (true: GPS, false: WiFi/Network)
timeout number Infinity 위치 요청 타임아웃 (밀리초)
maximumAge number 0 캐시된 위치의 최대 수명 (밀리초)
distanceFilter number 0 최소 이동 거리 (미터, 이 값만큼 이동 시 업데이트)

Returns: Promise<number> - Watch ID (clearWatch에 사용)

Example:

const watchId = await watchPosition({
  enableHighAccuracy: true,
  distanceFilter: 10, // 10m 이동마다 업데이트
});

// 나중에 중지할 때
clearWatch(watchId);

clearWatch(watchId)

특정 위치 추적을 중지합니다.

clearWatch(watchId: number): void

Parameters:

Name Type Description
watchId number watchPosition에서 반환된 ID

Example:

const watchId = await watchPosition();
// ...
clearWatch(watchId);

stopObserving()

모든 위치 추적을 중지합니다.

stopObserving(): void

Example:

stopObserving();

addLocationListener(callback)

위치 변경 이벤트 리스너를 추가합니다.

addLocationListener(
  callback: (position: GeolocationPosition) => void
): EmitterSubscription

Parameters:

Name Type Description
callback (position: GeolocationPosition) => void 위치 변경 시 호출될 함수

Returns: EmitterSubscription - 리스너를 제거할 수 있는 subscription

Example:

const subscription = addLocationListener((position) => {
  console.log('위치 업데이트:', position.coords);
});

// 나중에 제거
subscription.remove();

addErrorListener(callback)

위치 에러 이벤트 리스너를 추가합니다.

addErrorListener(
  callback: (error: GeolocationError) => void
): EmitterSubscription

Parameters:

Name Type Description
callback (error: GeolocationError) => void 에러 발생 시 호출될 함수

Returns: EmitterSubscription

Example:

const subscription = addErrorListener((error) => {
  console.error('위치 에러:', error.message);
});

removeAllListeners()

모든 이벤트 리스너를 제거합니다.

removeAllListeners(): void

Example:

removeAllListeners();

Types

GeolocationOptions

interface GeolocationOptions {
  timeout?: number; // 타임아웃 (ms)
  maximumAge?: number; // 캐시된 위치의 최대 수명 (ms)
  enableHighAccuracy?: boolean; // 고정밀도 모드 사용
  distanceFilter?: number; // 최소 이동 거리 (m)
  useSignificantChanges?: boolean; // 중요한 변화만 감지 (iOS)
}

GeolocationPosition

interface GeolocationPosition {
  coords: {
    latitude: number; // 위도
    longitude: number; // 경도
    altitude?: number; // 고도 (m)
    accuracy: number; // 수평 정확도 (m)
    altitudeAccuracy?: number; // 수직 정확도 (m)
    heading?: number; // 방향 (도, 0-360)
    speed?: number; // 속도 (m/s)
  };
  timestamp: number; // 타임스탬프 (ms)
}

GeolocationError

interface GeolocationError {
  code: number; // 에러 코드
  message: string; // 에러 메시지
}

Examples

1. 권한 체크 후 위치 가져오기

async function getLocation() {
  try {
    const status = await requestAuthorization();

    if (status === 'denied') {
      Alert.alert('권한 거부', '위치 권한이 필요합니다.');
      return;
    }

    const position = await getCurrentPosition({
      enableHighAccuracy: true,
      timeout: 15000,
    });

    console.log('현재 위치:', position.coords);
  } catch (error) {
    console.error('위치 가져오기 실패:', error);
  }
}

2. 실시간 위치 추적 (React Hook)

import { useEffect, useState } from 'react';
import { watchPosition, clearWatch, addLocationListener } from 'react-native-geolocation';
import type { GeolocationPosition } from 'react-native-geolocation';

function useGeolocation() {
  const [position, setPosition] = useState<GeolocationPosition | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let watchId: number | null = null;

    const startTracking = async () => {
      try {
        watchId = await watchPosition({
          enableHighAccuracy: true,
          distanceFilter: 10,
        });

        const subscription = addLocationListener((newPosition) => {
          setPosition(newPosition);
          setError(null);
        });

        return () => {
          subscription.remove();
        };
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Unknown error');
      }
    };

    startTracking();

    return () => {
      if (watchId !== null) {
        clearWatch(watchId);
      }
    };
  }, []);

  return { position, error };
}

// 사용
function App() {
  const { position, error } = useGeolocation();

  if (error) {
    return <Text>Error: {error}</Text>;
  }

  return (
    <View>
      <Text>위도: {position?.coords.latitude}</Text>
      <Text>경도: {position?.coords.longitude}</Text>
      <Text>속도: {position?.coords.speed ? `${(position.coords.speed * 3.6).toFixed(2)} km/h` : 'N/A'}</Text>
    </View>
  );
}

3. 거리 계산

import { getCurrentPosition } from 'react-native-geolocation';

// Haversine 공식으로 두 지점 간 거리 계산
function calculateDistance(
  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;
}

async function getDistanceFromTarget() {
  const targetLat = 37.5665;
  const targetLon = 126.978;

  const position = await getCurrentPosition();
  const distance = calculateDistance(
    position.coords.latitude,
    position.coords.longitude,
    targetLat,
    targetLon
  );

  console.log(`목표 지점까지 거리: ${distance.toFixed(2)} km`);
}

Platform-Specific Notes

iOS

  • CLLocationManager 사용
  • Info.plist에 권한 설명 필수
  • 시뮬레이터에서 테스트 시: Debug > Simulate Location 사용

Android

  • FusedLocationProviderClient 사용 (Google Play Services)
  • 자동으로 최적의 위치 제공자 선택 (GPS, WiFi, Cell)
  • 에뮬레이터에서 테스트 시: Extended Controls > Location 사용

Performance Tips

  1. High Accuracy는 필요할 때만 사용

    // 배터리 절약
    getCurrentPosition({ enableHighAccuracy: false });
  2. distanceFilter 활용

    // 100m 이동할 때만 업데이트
    watchPosition({ distanceFilter: 100 });
  3. 사용하지 않을 때는 추적 중지

    useEffect(() => {
      // 컴포넌트 언마운트 시 자동 중지
      return () => stopObserving();
    }, []);

Troubleshooting

iOS에서 권한 요청이 안 나타나요

Info.plistNSLocationWhenInUseUsageDescription이 있는지 확인하세요.

Android에서 위치가 업데이트되지 않아요

  1. Google Play Services가 설치되어 있는지 확인
  2. 기기의 위치 서비스가 켜져 있는지 확인
  3. 에뮬레이터에서는 Extended Controls로 위치 설정

watchPosition이 작동하지 않아요

  1. requestAuthorization()을 먼저 호출했는지 확인
  2. addLocationListener()로 이벤트 리스너를 등록했는지 확인
  3. 기기를 실제로 이동시키거나 시뮬레이션하고 있는지 확인

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT


Made with create-react-native-library

About

이 React Native Geolocation Library는 Promise 기반 비동기 API로 설계된 라이브러리입니다.

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages