위치 (GPS)
디바이스 GPS 위치 정보에 접근합니다.
개요
GPS 및 네트워크를 통한 현재 위치 조회를 지원합니다. Android와 iOS에서 동일한 JS API를 사용합니다.
| 기능 | Android | iOS |
|---|---|---|
| 현재 위치 조회 | ✓ (Android 7.0+) | ✓ (iOS 13+) |
| 위치 변경 감지 | ✓ (Android 7.0+) | ✓ (iOS 13+) |
지원 플랜: Basic 이상
iOS 전제조건
iOS에서 위치 기능을 사용하려면 Info.plist에 위치 권한 설명을 추가해야 합니다.
<key>NSLocationWhenInUseUsageDescription</key>
<string>현재 위치를 기반으로 서비스를 제공하기 위해 위치 정보가 필요합니다.</string>앱 심사를 통과하려면 권한 설명이 실제 사용 목적과 일치해야 합니다. 백그라운드 위치가 필요하면 NSLocationAlwaysAndWhenInUseUsageDescription도 추가하세요.
Android 권한 안내
Android에서 위치 기능을 사용하려면 먼저 AndroidManifest.xml에서 위치 권한을 주석 해제해야 합니다. SDK는 이 권한들을 기본적으로 주석 처리한 상태로 배포하므로, 실제로 사용하는 권한만 활성화하세요 (Google Play 데이터 안전성 정책).
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />SDK가 위치 권한을 요청할 때, Android 버전에 따라 사용자에게 표시되는 선택지가 다릅니다.
| Android 버전 | 사용자 선택지 |
|---|---|
| Android 11 이하 | 앱 사용 중 허용 / 한 번 허용 / 거부 |
| Android 12 ~ 16 | 정밀 위치 또는 대략적 위치 중 선택 가능 |
| Android 17+ | "앱 사용 중에만" 정밀 위치를 임시 부여하는 옵션 추가 |
사용자가 **대략적 위치(Approximate)**를 선택하면 반경 약 3km 수준의 좌표가 반환됩니다. SDK는 정밀 위치(ACCESS_FINE_LOCATION)를 요청하지만 사용자 선택을 강제할 수 없습니다.
Android 17에서 추가된 임시 정밀 위치 옵션을 선택하면, 앱이 백그라운드로 이동한 뒤 다시 위치를 요청할 때 권한이 만료되어 있을 수 있습니다. SDK는 이 경우를 자동으로 처리합니다 — 권한이 없으면 권한 요청 다이얼로그를 다시 표시하고, 위치 획득에 실패하면 isSuccess: false로 콜백이 호출됩니다.
현재 위치 조회
window.unveilyBridge.location.get({
accuracy: "high", // "high" | "medium" | "low"
timeout: 10000, // 최대 대기 시간 (ms)
onResult: "onLocationResult",
onError: "onLocationError"
});
function onLocationResult(result) {
const { latitude, longitude, accuracy } = JSON.parse(result);
console.log(`위도: ${latitude}, 경도: ${longitude}, 정확도: ${accuracy}m`);
}
function onLocationError(error) {
const { code, message } = JSON.parse(error);
if (code === "PERMISSION_DENIED") {
alert("위치 권한을 허용해 주세요.");
}
}응답 구조
{ "latitude": 37.5665, "longitude": 126.9780, "accuracy": 15.0 }위치 변경 감지 (지속 수신)
window.unveilyBridge.location.watch({
minDistance: 10, // 최소 이동 거리(m) 이상일 때 콜백
onUpdate: "onLocationUpdate"
});
function onLocationUpdate(result) {
const { latitude, longitude } = JSON.parse(result);
updateMap(latitude, longitude);
}
// 감지 중지
window.unveilyBridge.location.stopWatch();에러 코드
| 코드 | 설명 |
|---|---|
PERMISSION_DENIED | 위치 권한 없음 |
TIMEOUT | 지정 시간 내 위치를 가져오지 못함 |
UNAVAILABLE | GPS 또는 네트워크 위치 사용 불가 |
서버측 위치 저장
app.post('/api/location', (req, res) => {
const { latitude, longitude } = req.body;
const userId = req.session.userId;
db.query(
'INSERT INTO user_locations (user_id, latitude, longitude, recorded_at) VALUES (?, ?, ?, NOW())',
[userId, latitude, longitude]
);
res.json({ ok: true });
});[HttpPost("location")]
[Authorize]
public async Task<IActionResult> SaveLocation([FromBody] LocationRequest request)
{
await _locationService.SaveAsync(User.GetUserId(), request.Latitude, request.Longitude);
return Ok(new { ok = true });
}@PostMapping("/api/location")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<?> saveLocation(@RequestBody LocationRequest request,
@AuthenticationPrincipal UserDetails user) {
locationService.save(user.getUsername(), request.getLatitude(), request.getLongitude());
return ResponseEntity.ok(Map.of("ok", true));
}<?php
$data = json_decode(file_get_contents('php://input'), true);
$stmt = $pdo->prepare(
'INSERT INTO user_locations (user_id, latitude, longitude, recorded_at) VALUES (?, ?, ?, NOW())'
);
$stmt->execute([$_SESSION['user_id'], $data['latitude'], $data['longitude']]);
echo json_encode(['ok' => true]);<%
Dim lat, lng
lat = Request.Form("latitude")
lng = Request.Form("longitude")
Dim conn
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open Application("ConnectionString")
conn.Execute "INSERT INTO user_locations (user_id, latitude, longitude) VALUES (" & _
Session("user_id") & ", " & lat & ", " & lng & ")"
Response.ContentType = "application/json"
Response.Write "{""ok"": true}"
%>