2016년 11월 1일 화요일

[안드로이드] 유니크 ID 사용하기

안드로이드에서 ID를 고려할 떄의 규칙

  1. 기능적으로 요구되는 제약사항이 있을 때를 제외하고, SSAIDISettings.Secure.ANDROID_ID),IMEI와 같은 하드웨어에 종속된 아이디는 대부분의 상황에서 피하는 것이 좋다.
  2. Google Play Service 에서는 Ad ID를 제공한다. 이 Ad ID는 광고, 유저(디바이스)식별 용으로만 사용한다.
  3. 2번의 경우를 제외하고, 대부분의 경우에서는 UUID를 내부적으로 저장하여 사용한다. 단, 부정방지, 전화통화(telephony) 용도로는 사용하면 안된다.
  4. ID의 Scope 범위, 리셋여부 등을 고려하여 가장 알맞는 방법을 이용한다.

MAC Address는??

MAC주소는 모든 디바이스를 통틀어서 유니크하고, 하드웨어 속성이므로 사용자가 리셋할 수도 없다. 그렇지만 유저의 식별자로는 가급적 권장되지 않는다. 더욱이, 안드로이드 6.0(API 23)부터는 로컬 디바이스(Wifi, 블루투스)의 MAC주소를 API를 통해 얻어올 수 없다. 기존에 존재하던 MAC주소를 반환하는 API는 공통적으로 02:00:00:00:00:00을 리턴할 것이다.

구글의 Ad ID

Google Play Service의 API를 이용하여 Ad ID를 얻을 수 있다. 이 Ad ID는 디바이스에 내장된 Google Play Service와 연관되어 있으며, 유저식별용으로 사용하기에 적합하다. 단점으로는, Google Play Service가 없는 디바이스에서는 사용불가능하다.(ex 가상머신에서는 사용불가능) Ad ID를 얻으려면 다음과 같이 한다.
1.build.gradle에 GooglePlayService를 추가한다.
...
dependencies {
    ...
    compile 'com.google.android.gms:play-services:9.4.0'
    compile 'com.google.android.gms:play-services-auth:9.4.0'
    ...
}
...
2.AdvertisingIdClient 클래스의 getAdvertisingIdInfo(Context)메서드를 통해 Info 클래스의 인스턴스를 얻고, 이 인스턴스의 getId()를 호출하여 id를 얻는다.(이 작업은 백그라운드 스레드에서 수행해야 한다.)
private class GoogleAppIdTask extends AsyncTask<Void, Void, String> {
        protected String doInBackground(final Void... params) {
            String adId = null;
            try {
                adId = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext()).getId();
                Logger.logDebug("adid : " + adId);
            } catch (IllegalStateException ex) {
                ex.printStackTrace();
                Logger.logError("IllegalStateException");
            } catch (GooglePlayServicesRepairableException ex) {
                ex.printStackTrace();
                Logger.logError("GooglePlayServicesRepairableException");
            } catch (IOException ex) {
                ex.printStackTrace();
                Logger.logError("IOException");
            } catch (GooglePlayServicesNotAvailableException ex) {
                ex.printStackTrace();
                Logger.logError("GooglePlayServicesNotAvailableException");
            }
            return adId;
        }

        protected void onPostExecute(String adId) {
            //TODO::Ad ID를 이용한 작업 수행
        }
    }

UUID

자바에서는 기본적으로 UUID를 생성하는 클래스를 지원하고 있다. 이렇게 UUID를 생성하면 간단하게 유니크한 ID를 얻을 수 있다. 대신, 이 ID는 앱의 내부저장소에 저장해두어야 하는데, 사용자가 내부저장소를 지우거나, 앱을 삭제 후 재설치하는 경우 ID가 달라질 수 있다. UUID를 얻으려면 다음의 코드를 추가한다.
String uniqueID = UUID.randomUUID().toString();

ID의 특징

ID는 다음과 같은 특징이 있는데, 사용하는 이유와 목적에 따라 적절한 ID를 선택하는 것이 좋다.

Scope

안드로이드에서는 다음 3가지 경우의 Scope가 존재한다.
  • Single 앱의 ID : 다른 앱과 ID를 공유하지 않음
  • 앱 그룹별 ID : 관련된 앱끼리 미리 정의하여 공유
  • 디바이스 ID : 모든 앱이 이용할 수 있는 디바이스 고유 ID

리셋가능 vs 변경불가능

안드로이드에서는 다음 4가지 경우의 케이스가 존재한다.
  • Session-only : 앱이 재시작될 때마다 새로운 ID 발급
  • Install-reset : 앱 재설치 때마다 새로운 ID 발급(내부저장소 삭제와 동일)
  • FDR-reset : 공장초기화 때마다 새로운 ID 발급
  • FDR-persistent - 공장초기화 후에도 ID 변경없음

결론

ID정책을 매번 논의하는 것은 매우 번거로운 절차이다. 그러므로, 구글에서 제시하는 가이드대로 Ad IDUUID중 필요에 따라 적절히 사용하면 대부분의 앱에서 커버가능할 것으로 예상된다.
  • Ad ID
    • 디바이스 식별 용도로 사용가능
    • Scope : 그룹 ID(구글플레이를 사용하기로 약속한 모든 앱에서 이용가능하므로 디바이스 ID라고 봐도 무방)
    • FDR-reset : 공장초기화 후 ID 변경됨(구글플레이를 지울 수 있는 방법이 없다.)
    • 구글플레이가 설치되어있는 디바이스에서만 가능(현존하는 대부분의 안드로이드 디바이스는 모두 설치되어있다.)
  • UUID
    • 앱, 메시지 식별 용도로 사용가능. 디바이스 식별도 가능하지만, 사용자의 액션에 따른 변경가능성 있음.
    • Scope : Single 앱의 ID(randomUUID()메서드 호출시마다 새로운 UUID 생성됨)
    • Session-only(발급받은 ID를 내부저장소에 저장할 경우, install-reset)
    • 새로 생성되는 ID를 내부저장소에 저장하여 관리할 수 있으나, 사용자가 앱의 데이터 삭제 or 재설치를 수행하면 ID가 변경된다.

참고자료

댓글 5개:

  1. 안녕하세요 포스팅 잘봤습니다.
    근데 이해안가는 부분이 있어서 댓글을 남깁니다.
    FDR-persistent 에 해당하는 아이디는 안드로이드에서 없는건가요?
    제가 보기로는 속성 설명정도로만 이해됩니다.

    답글삭제
  2. 안녕하세요 포스팅 잘봤습니다.
    근데 이해안가는 부분이 있어서 댓글을 남깁니다.
    FDR-persistent 에 해당하는 아이디는 안드로이드에서 없는건가요?
    제가 보기로는 속성 설명정도로만 이해됩니다.

    답글삭제
    답글
    1. 안녕하세요!
      FDR-persistent 에 해당하는 아이디는 보통 하드웨어에 종속적인 ID값인 경우입니다. 위에서 언급했던 SSAIDISettings.Secure.ANDROID_ID 나 MAC Address(6.0 이상에서는 API를 통해 얻어올 수 없음)가 FDR-Persistent의 케이스라고 볼 수 있겠네요.

      삭제
  3. Xamarin.Android에서는 Android6.0 이상에서도 Mac Address를 가져 올 수 있습니다. 감사합니다.

    답글삭제