본문 바로가기
Swift

CoreLocation) 위치 데이터의 정확성에 대한 고찰

by 김 Duke 2024. 2. 16.

목차

     

    CoreLocation을 통해 위치 정보 데이터를 이용하다보면 위치의 정확성과 마주하게 된다.

    난 분명 가만히 있는데 위치가 들쭉날쭉한다든지, 걷고 있는데 내 위치가 하천 위를 걷고 있다든지

    실제 위치와 다르게 표현되는 경우가 있다. 이럴 경우 몇몇 설정을 통해 더 정확한 데이터를 얻을 수 있다.

    하지만 정확한 데이터를 얻기 위해선 더 많은 에너지가 요구되는 법으로, 여기서 에너지는 배터리를 말할 수 있다.

    정확한 데이터를 지속적으로 얻다보면 더 많은 배터리량을 소모하게 된다. 

    또한 물리적인 기기를 통해 데이터를 얻는게 아닌, GPS, Cellular, WIFI 데이터를 통해 위치 데이터를 얻는 것이다 보니 

    종종 잘못된 데이터를 얻기도 한다.

     

    그래서 오늘 다룰 내용은 정확성에 관여하는 프로퍼티들을 소개하고 정확한 혹은 대략적인 데이터를 얻는 설정에 대해 알아보고,

    추가로 잘못된 데이터를 얻지 않는 방법에 대해 알아보고자 한다.

    만약 CoreLocation과 CLLocationManager 클래스에 대해 초면이라면 https://yahoth.tistory.com/20 여기서 기본 구성에 대해 확인할 수 있다.

     

     

    정확성 관련 프로퍼티

    해당 글에서는 직접적으로 정확성을 설정하는 두 가지 프로퍼티와 간접적으로 설정하는 한 가지 프로퍼티를 소개한다.

     

    직접적으로 정확성을 설정

    - desiredAccuracy

    - distanceFilter

     

    간접적으로 설정

    -activityType

     

    desiredAccuracy: 원하는 정확도

    위치 정보 데이터를 사용하는 어플(지도맵, 내비게이션맵)을 이용하다 보면 내 위치가 실제거리보다 먼거리로 표현되는 경우가 있다.

    이런 경우 desiredAccuracy 프로퍼티를 통해 그 간극을 조절할 수 있다.

    이 프로퍼티는 Standard Location Service(표준 위치 서비스)에 영향이 있고, Significant Location Changes에는 영향이 없다. 

    (이에 대한 자세한 것은 https://yahoth.tistory.com/20에 위치 정보를 받을 수 있는 API들에 대해 정리해 두었다.)

     

    이름에서 말해주듯, 내 앱이 사용하려고 하는 위치 데이터의 정확도이다.

    https://developer.apple.com/documentation/corelocation/cllocationmanager/1423836-desiredaccuracy

     

     

    더 자세한 정보를 알기 위해 CLLocationAccuracy를 알아보면,

     

    https://developer.apple.com/documentation/corelocation/cllocationaccuracy

     

     

     

     

    지리적 좌표(coordinate)의 정확성이라는 설명을 볼 수 있다.

    이것은 CLLocation 객체가 가진 coordinate가 나타내는 위치와 실제 위치 사이의 거리(meters)라고 볼 수 있다.

    정확도가 높아질 수록 잡아먹는 배터리용량이 점점 커지기 때문에 앱의 필요에 맞게 정확도를 조절할 수 있다.

    CLLocationAccuracy는 Double값이고 단위는 meter이다.

     

    예를 들어 현재 위치를 얻으려고 할 때

     

    locationManager.desiredAccuracy = 1000

     

     

    CLLocationAccuracy값이 1000(1km)이면 내 위치 반경 1km 내의 coordinate를 얻을 수 있다는 뜻이다.

    아래에 그림으로 표현해봤다. 

     

     
     
     

     

     

    CoreLocation에선 정확도를 일일이 숫자로 쓰지 않아도 되게끔 정확도 관련 상수를 제공해준다.
     
    kCLLocationAccuracyBestForNavigation: 가장 높은 수준의 정확도이다.
    문서의 설명을 보면 이 수준의 정확도를 사용할 땐 충전 상태에서 사용하길 권장한다.
     
    kCLLocationAccuracyBest: desiredAccuracy를 따로 설정하지 않았을 경우 iOS일 경우 default값이다.
    kCLLocationAccuracyBestForNavigation 만큼의 정확도가 필요하지 않을 때 사용하길 권장한다.
    내비게이션을 사용하지 않을 때 쓸 수 있는 가장 높은 수준의 정확도이다.
     
    그 이외에는 이름에 나와있든 10미터, 100미터 등으로 이해할 수 있다.
     

     

     

    주의사항

    위의 상수들 중 가장 마지막 상수를 보면 kCLLocationAccuracyReduced를 볼 수 있다.

    이는 isAuthorizedForPreciseLocation이 false일 경우 설정되는 기본 값인데, 이 경우 다른 정확도 값들을 설정해도 kCLLocationAccuracyReduced로 설정된다. 

     

    isAuthorizedForPreciseLocation는 따로 프로퍼티가 존재하는 것이 아닌 위치 권한 요청 시 설정가능한 정확한 위치 를 말한다.

     

     


     

     

    distanceFilter: 거리 필터

    distanceFilter의 경우 startUpdatingLocation이 시작된 후 위치가 업데이트 되기 위한 최소한의 수평 거리(meter)이다.

    desiredAccuracy와 마찬가지로 이 프로퍼티는 Standard Location Service(표준 위치 서비스)에 영향이 있고, Significant Location Changes나 이외 Visits Service에는 영향이 없다. 

     

    https://developer.apple.com/documentation/corelocation/cllocationmanager/1423500-distancefilter

     

    예를 들어 distanceFilter를 1(meter)로 설정하게 되면 이전에 측정된 위치에서 1meter의 거리를 움직이지 않는 이상 위치가 업데이트 되지 않는 것이다. 높은 값을 설정할 수록 그에 맞는 큰거리를 움직이지 않는 이상 업데이트는 시작되지 않는다.

    친절하게 가장 큰 거리에 대한 상수를 제공한다: CLLocationDistanceMax

    (그럼 이렇게 생각할 수 있다. 위치 업데이트가 안됐는데 이전에 측정된 위치를 어떻게 알아?

    그에 대한 답변은 startUpdatingLocation 메소드가 호출되는 순간 1회 위치 업데이트가 된다.)

    locationManager.distanceFilter = 1

     

     

    반면 distanceFilter의 defalut값인 kCLDistanceFilterNone을 사용한다면 제자리에 가만히 있더라도 위치 정보가 업데이트가 된다.

    locationManager.distanceFilter = kCLDistanceFilterNone

     


     

     

     

    위의 두가지 프로퍼티는 직접적으로 정확도를 설정한다면, 간접적으로 정확도를 설정하는 프로퍼티를 소개한다.

    activityType: 활동 유형

    https://developer.apple.com/documentation/corelocation/cllocationmanager/1620567-activitytype

     

    위치 정보를 받는 동안에 사용자의 위치정보 변화가 통상 이럴 것이다~라고 앱이 예측할 수 있게 해주는 활동 유형이다.

    쉽게 얘기하자면, 위치 정보를 받는 동안에 사용자가 걷고 있는지, 운전하고 있는지, 비행 중인지 등의 활동 유형을 설정하는 것이다.

     

    그렇다면 유형은 왜 선택해야하는가?

     

    바로 배터리 수명을 절약할 수 있게 도와주기 때문이다. 

    위치정보를 이용하는 앱은 activityType(활동 유형)에 따라 위치정보를 자동으로 일시정지하는 타이밍을 잡을 수 있다.

    (정확도 관련 부분은 예시 아래 부분에서 다룬다)

     

    예시

    activityType을 운전 중(주행 모드: automotiveNavigation)으로 선택하는 경우 차량이 오랜기간 움직이지 않으면 위치 업데이트를 정지시킨다. 또는 실내운동(fitness)을 선택하는 경우, 사용자가 일정 시간 동안 상당한 거리를 이동하지 않는 경우 위치 업데이트를 정지시킨다. 이는 실내운동의 경우 위치가 크게 변동되지 않고, 실내이기때문에 위치 추적이 불필요하거나 부정확할 수 있기 때문이다.

    이렇기 때문에 사용자의 앱 의도에 맞게 사용하면 배터리 수명을 절약할 수 있다.

    https://developer.apple.com/documentation/corelocation/clactivitytype


     

     

    첫번째.  ActivityType이 정확도에 관여하는 부분

    activityType 유형 중 "airbone" 은 더 높은 수직 정확도를 갖는다.

     

    CLLocation 객체는 객체의 coordinate와 고도 관련 프로퍼티들(altitude 등)의 정확도를 나타내는 프로퍼티가 존재한다.

    // 수평 정확성(coordinate의 정확성)
    var horizontalAccuracy: CLLocationAccuracy { get }
    // 수직 정확성(고도 정확성)
    var verticalAccuracy: CLLocationAccuracy { get }

     

     

    두 프로퍼티 값이 0과 가까울 수록 각각 coordinate와 altitude(이외 고도 관련 프로퍼티들)의 정확도가 정확하다는 뜻이다. 

    두 프로퍼티의 자세한 설명은 아래 [부정확한 위치 데이터를 피하는 법]에서 볼 수 있다.

     

    그래서 이 값을 가지고 activityType이 정확도에 미치는 영향을 주는 것을 테스트 해본 결과, 유의미한 결과를 찾을 수 있었다.

     

    테스트 환경
    -iPhone 12 Pro Max 
    -iOS 17.3.1
    -desiredAccuracy =  kCLLocationAccuracyBestForNavigation
    -distanceFilter = kCLDistanceFilterNone
    -야외에서 약 3-4km/h의 걷기
    -각 값은 30초씩 테스트 후 정확도들의 평균값이다.
    -참고사항: 앱 구동 후 첫 위치업데이트를 시작한 직후 약 30초 간은 보다 정확한 값이 측정되었기에 이때의 측정 값은 제외하였음.

     

     

     

     

    테스트 결과

    AcitivityType 5가지를 같은 환경에서 테스트한 결과, 위의 4가지 타입은 정확도 면에서 큰 차이가 없었다.

    하지만 airbone 타입에서는 유의미한 결과가 있었는데, verticalAccuracy가 다른 4타입보다 더 작은 값이 나왔고,

    이는 수직 정확도 측면에서 다른 4가지 타입보다 airbone의 수직 정확도가 더 유의미하다는 것을 확인할 수 있다.

     


     

    두번째.  ActivityType이 정확도에 관여하는 부분

    activityType의 공식문서에서 case들의 설명을 보고 있으면 도로망과 관련하여 언급한 부분이 있다.

    1. automotiveNavigation의 경우 도로망을 따라(following road network) 움직이는 경우
    2. otherNavigation의 경우 도로망을 준수하지 않거나, 이용하지 않을 수 있는 경우(don’t or may not adhere to roads)

     

    이 부분을 볼 땐 더 정확한 설명이 없었기에 알아차리지 못했다.

    하지만 구글링 중 이에 관해 다루는 내용을 발견했고 내용은 이렇다.

     

    AcitivityType이 업데이트된 좌표 데이터가 가까운 도로에 "스냅"되는 방식에 영향을 끼칠 수 있다.

     

    요약하자면 "Other Navigation" 활동 유형을 사용하지 않고, 위치가 빠르게 변하고 있을 경우(즉, 충분히 빠른 차량 등에 타고 있을 경우), 그리고 어떻게든 핸드폰이 인터넷이나 로컬 캐시를 통해 필요한 정보를 얻을 수 있다면, 관리자가 보고하는 위치는 정확하지 않을 수 있다. 이는 위치가 가장 가까운 도로에 "스냅"되기 때문이다. "스냅"이란 말은 위치가 가장 가까운 도로에 맞춰진다는 의미로, 이는 차량이 도로를 따라 움직이는 것을 가정하고 위치를 보정하는 방식을 의미한다. 이런 방식은 일반적으로 자동차 내비게이션에서 유용하나, 실제 위치와는 다소 차이가 있을 수 있다.

     

    Difference between CLActivityType values - iOS SDK

    What is the difference between those values: CLActivityTypeAutomotiveNavigation, CLActivityTypeFitness, CLActivityTypeOtherNavigation, When assigned to activityType property of CLLocationManager?

    stackoverflow.com

    https://stackoverflow.com/questions/16101051/control-ios-gps-input/25165400#25165400

     

    Control iOS gps input

    I have a problem with iPhone GPS ; i'm trying to record a track that is not on a street , but each time I pass near a street ( look at enclosed image ) it seems to me that the gps output is corrected

    stackoverflow.com

     

    해당 문제는 수 년전에 제기된 문제로 구글링 했을 때 많은 케이스를 발견할 수 있었다. 하지만 애플의 공식적인 답변 및 해결책, 또한 관련한 내용을 문서에서 확인할 수 없었다.

    그러므로 최소한 좌표가 가까운 도로에 스냅되는 문제를 겪지 않기 위해 도로를 이용하지 않는 유형을 이용할 땐 otherNavigation을 사용하도록 하자.

     

     

    부정확한 위치 데이터를 피하는 방법

    위에서 설명한 horizontalAccuracy, verticalAccuracy를 포함한 CLLocation 객체가 갖는 정확도 관련 프로퍼티를 사용할 수 있다.

     

    horizontalAccuracy

    : 좌표의 정확도, 음수일 경우 좌표가 유효하지 않음, 작을 수록 정확, 단위: meter

    예시
    horizontalAccuracy 값이 10(meter)이다
    : "실제 위치의 수평 반경 10m 안에 좌표 데이터가 있다."

     

     

    verticalAccuracy

    : 고도의 정확도, 0 또는 음수일 경우 고도 값이 유효하지 않음, 작을 수록 정확

    또한 verticalAccuracy에는 추가 설명이 있는데, verticalAccuracy값이 68% 확률로 정확하다고 한다.

    예시
    verticalAccuracy 값이 10(meter)이다
    68%확률로 "실제 위치의 수직 반경 10m 위 아래로  고도 데이터가 있다."

     

     

    speedAccuracy

    : 속도의 정확도, 음수일 경우 유효하지 않음, 작을 수록 정확, 단위: meter

    예시
    speedAccuracy 값이 10(meter)이다
    "실제 속도의 +- 10m 범위 안에 speed 데이터가 있다.

     

    courseAccuracy

    : 방향의 정확도, 음수일 경우 유효하지 않음, 작을 수록 정확, 단위: meter

    예시
    verticalAccuracy 값이 10(meter)이다
    "실제 방향의 +- 10m 범위 안에 course 데이터가 있다.

     

     

     

    CLLocation객체를 이용하여 위치 데이터를 사용할 때 정확도 프로퍼티들을 이용하면 부정확한 데이터를 피할 수 있다.

     

    https://developer.apple.com/documentation/corelocation/cllocation/1423599-horizontalaccuracy

     

    horizontalAccuracy | Apple Developer Documentation

    The radius of uncertainty for the location, measured in meters.

    developer.apple.com

    https://developer.apple.com/documentation/corelocation/cllocation/1423550-verticalaccuracy

     

    verticalAccuracy | Apple Developer Documentation

    The validity of the altitude values, and their estimated uncertainty, measured in meters.

    developer.apple.com

    https://developer.apple.com/documentation/corelocation/cllocation/3524340-speedaccuracy

     

    speedAccuracy | Apple Developer Documentation

    The accuracy of the speed value, measured in meters per second.

    developer.apple.com

    https://developer.apple.com/documentation/corelocation/cllocation/3524338-courseaccuracy

     

    courseAccuracy | Apple Developer Documentation

    The accuracy of the course value, measured in degrees.

    developer.apple.com

     

     

     

    결론

    위에서 소개한 프로퍼티들을 이용하여 앱에 필요한 수준의 정확도와 배터리 수명을 고려하여 사용한다면 더 좋은 수준의 앱을 만드는데 도움이 될 것이다. 

     

    또한 아무리 높은 수준의 정확도를 설정하더라도, 기기의 환경에 따라 설정 수준보다 낮은 수준의 정확도를 가진 데이터가 업데이트 될 수도 있다. 이 경우 추가적인 알고리즘을 통해 정확도를 높이는 방법이 필요할 것으로 보인다.


    TOP

    Designed by 티스토리