블로그 목록

expo-location으로 현재 위치 가져오기 — 권한부터 좌표, 주소 변환까지

"내 주변" 기능을 붙이려다 위치 권한에서 한참 헤맸다. 좌표를 받는 것 자체는 몇 줄인데, 권한을 물어보는 타이밍과 거부됐을 때 처리를 대충 짜니까 앱이 계속 멈춰 있는 것처럼 보였다. Expo에서는 expo-location으로 이걸 정리할 수 있다.

설치와 권한 설정

npx expo install expo-location

위치는 민감 권한이라 app.json에 사용 목적 문구를 넣어야 한다. 안 넣으면 iOS 심사에서 바로 반려된다.

{
  "expo": {
    "plugins": [
      [
        "expo-location",
        { "locationWhenInUsePermission": "주변 매장을 찾기 위해 위치를 사용합니다." }
      ]
    ]
  }
}

권한 먼저, 좌표는 그 다음

핵심은 순서다. 무조건 getCurrentPositionAsync부터 부르지 말고, 권한을 요청해서 승인됐을 때만 좌표를 받아야 한다.

import * as Location from 'expo-location';
import { useState } from 'react';
import { Button, Text, View } from 'react-native';

export function NearbyButton() {
  const [address, setAddress] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const findMe = async () => {
    const { status } = await Location.requestForegroundPermissionsAsync();
    if (status !== 'granted') {
      setError('위치 권한이 필요합니다. 설정에서 허용해 주세요.');
      return;
    }

    const { coords } = await Location.getCurrentPositionAsync({
      accuracy: Location.Accuracy.Balanced,
    });

    // 좌표를 사람이 읽을 주소로 변환
    const [place] = await Location.reverseGeocodeAsync(coords);
    setAddress(`${place.city} ${place.district ?? ''} ${place.street ?? ''}`.trim());
  };

  return (
    <View>
      <Button title="내 위치 찾기" onPress={findMe} />
      {address && <Text>{address}</Text>}
      {error && <Text>{error}</Text>}
    </View>
  );
}

reverseGeocodeAsync가 은근 유용하다. 위도·경도만 있으면 도시·구·도로명을 돌려줘서, 지도 없이 텍스트로만 "여기가 어디"를 보여줄 때 별도 API를 붙일 필요가 없다.

두 가지만 챙기면 된다

  • 정확도는 상황에 맞게. Accuracy.Highest는 GPS를 세게 돌려서 배터리를 먹는다. 매장 찾기 정도면 Balanced로 충분하고, 응답도 더 빠르다.
  • 거부 상태를 항상 처리하자. 사용자가 한 번 거부하면 다음부터 시스템 팝업이 안 뜬다. 이럴 땐 앱 안에서 안내 문구를 띄우고 Linking.openSettings()로 설정 화면으로 보내주는 게 정석이다.

권한 요청 → 승인 확인 → 좌표 → 주소 변환. 이 순서만 지키면 위치 기능은 생각보다 금방 붙는다. 실시간 추적이 필요하면 watchPositionAsync로 넘어가면 되는데, 대부분의 "내 주변" 기능은 이 한 번의 조회면 끝난다.