자동 백업으로 사용자 데이터 백업

앱의 자동 백업은 Android 6.0(API 수준 23) 이상에서 타겟팅하거나 실행되는 앱의 사용자 데이터를 자동으로 백업합니다. Android는 앱 데이터를 사용자의 Google Drive에 업로드하여 보존하며, 이곳의 앱 데이터는 사용자의 Google 계정 사용자 인증 정보에 따라 보호됩니다. 백업은 Android 9 이상을 실행하는 기기에서 기기의 PIN이나 패턴, 비밀번호를 사용하여 엔드 투 엔드 암호화됩니다. 데이터양은 사용자당 25MB로 제한됩니다. 백업 데이터 저장은 무료입니다. 앱에서 백업 절차를 맞춤설정하거나 백업을 사용 중지하여 선택 해제할 수 있습니다.

Android의 백업 옵션 개요와 백업 및 복원할 데이터에 관한 안내는 데이터 백업 개요를 참고하세요.

백업되는 파일

기본적으로 자동 백업에는 시스템에서 앱에 할당하는 대부분의 디렉터리에 있는 다음과 같은 파일이 포함됩니다.

getCacheDir(), getCodeCacheDir(), getNoBackupFilesDir()에서 반환한 디렉터리에 있는 파일은 자동 백업에서 제외됩니다. 이 위치에 저장된 파일은 일시적으로만 필요하며 백업 작업에서 의도적으로 제외됩니다.

특정 파일을 포함하거나 제외하도록 앱을 구성할 수 있습니다. 자세한 내용은 파일 포함 및 제외 섹션을 참고하세요.

백업 위치

백업 데이터는 사용자의 Google Drive 계정에 있는 비공개 폴더에 저장되며 앱당 25MB로 제한됩니다. 저장된 데이터는 사용자의 개인 Google Drive 할당량에 포함되지 않습니다. 또한 최근 백업만 저장됩니다. 백업이 진행되면 이전의 모든 백업은 삭제됩니다. 기기의 사용자나 다른 앱은 백업 데이터를 읽을 수 없습니다.

사용자는 Google Drive Android 앱에 백업된 앱 목록을 볼 수 있습니다. Android 지원 기기의 경우 사용자는 설정 > 백업 및 재설정 아래에 있는 Drive 앱의 탐색 창에서 이 목록을 찾을 수 있습니다.

다음 예에서 설명하는 바와 같이 백업은 기기 설정의 전체 기간별로 별도의 데이터 세트에 저장됩니다.

  • 사용자가 두 대의 기기를 소유하고 있다면 백업 데이터 세트는 기기별로 존재합니다.

  • 사용자가 기기를 초기화한 다음 동일한 계정으로 기기를 설정하면 백업이 새 데이터 세트에 저장됩니다. 사용하지 않는 데이터 세트는 일정 기간 활동이 없으면 자동으로 삭제됩니다.

백업 일정

다음 조건이 모두 충족되면 자동 백업이 실행됩니다.

  • 사용자가 기기에 백업을 사용 설정했습니다. Android 9의 경우 이 설정이 설정 > 시스템 > 백업에 있습니다.
  • 마지막 백업 후 24시간 이상 경과했습니다.
  • 기기가 유휴 상태입니다.
  • 기기가 Wi-Fi 네트워크에 연결되어 있습니다 (기기 사용자가 모바일 데이터 백업을 선택하지 않은 경우).

실제로 이러한 조건은 거의 매일 밤 발생하지만 기기에서 전혀 백업을 실행하지 않을 수 있습니다 (예: 기기가 네트워크에 연결되지 않는 경우). 네트워크 대역폭을 절약하기 위해 업로드는 앱 데이터가 변경된 경우에만 실행됩니다.

자동 백업을 하는 동안 시스템은 앱을 종료하여 앱이 더 이상 파일 시스템에 쓰지 않도록 합니다. 기본적으로 백업 시스템은 사용자 환경이 저하되지 않도록 포그라운드에서 실행 중인 앱을 무시합니다. android:backupInForeground 속성을 true로 설정하여 기본 동작을 재정의할 수 있습니다.

테스트를 간소화하기 위해 Android에는 앱의 백업을 수동으로 시작할 수 있는 도구가 포함되어 있습니다. 자세한 내용은 백업 및 복원 테스트를 참고하세요.

복원 일정

Play 스토어에서 앱을 설치하든, 기기 설정 중에 앱을 설치하든 (시스템이 이전에 설치된 앱을 설치하는 경우) adb 설치를 실행하든 앱이 설치될 때마다 데이터가 복원됩니다. 복원 작업은 APK가 설치된 후, 사용자가 앱을 시작할 수 있게 되기 전에 일어납니다.

초기 기기 설정 마법사가 진행되는 동안 사용 가능한 백업 데이터 세트 목록, 그리고 어떤 데이터 세트의 데이터를 복원할지 묻는 메시지가 사용자에게 표시됩니다. 백업 데이터 세트를 선택하면 그 데이터 세트가 기기의 상위 데이터 세트가 됩니다. 기기는 자체 백업 또는 상위 데이터 세트에서 복원할 수 있습니다. 두 소스의 백업을 모두 사용할 수 있는 경우 기기는 자체 백업에 우선순위를 둡니다. 사용자가 기기 설정 마법사를 진행하지 않았다면 기기는 자체 백업에서만 복원할 수 있습니다.

테스트를 간소화하기 위해 Android에는 앱 복원을 수동으로 시작할 수 있는 도구가 포함되어 있습니다. 자세한 내용은 백업 및 복원 테스트를 참고하세요.

백업 사용 설정 및 중지

Android 6.0(API 수준 23) 이상을 타겟팅하는 앱은 자동 백업에 자동으로 포함됩니다. 앱 매니페스트 파일에서 android:allowBackup에 불리언 값을 설정하여 백업을 사용 설정 또는 사용 중지합니다. 기본값은 true이지만 다음 예와 같이 매니페스트에 이 속성을 명시적으로 설정하는 것이 좋습니다.

<manifest ... >
    ...
    <application android:allowBackup="true" ... >
        ...
    </application>
</manifest>

android:allowBackupfalse로 설정하여 백업을 사용 중지할 수 있습니다. 앱이 다른 메커니즘을 통해 상태를 다시 만들 수 있거나 앱이 민감한 정보를 처리하는 경우 이렇게 하는 것이 좋습니다.

파일 포함 및 제외

시스템에서는 기본적으로 모든 앱 데이터를 백업합니다. 자세한 내용은 백업되는 파일 섹션을 참고하세요.

이 섹션에서는 맞춤 XML 규칙을 정의하여 백업 대상을 제어하는 방법을 보여줍니다. 앱이 Android 12 (API 수준 31) 이상을 타겟팅하는 경우 이 섹션에 설명된 대로 추가 XML 백업 규칙 세트를 지정하여 이러한 Android 버전을 실행하는 기기에 도입된 백업 복원 변경사항을 지원해야 합니다.

Android 11 이하에서 백업 제어

Android 11 (API 수준 30) 이하를 실행하는 기기에서 백업되는 파일을 제어하려면 이 섹션의 단계를 따르세요.

  1. 다음 예와 같이 AndroidManifest.xml 파일에서 <application> 요소에 android:fullBackupContent 속성을 추가합니다. 이 속성은 백업 규칙이 포함된 XML 파일을 가리킵니다.

    <application ...
     android:fullBackupContent="@xml/backup_rules">
    </application>
    
  2. res/xml/ 디렉터리에 @xml/backup_rules이라는 XML 파일을 만듭니다. 이 파일에 <include><exclude> 요소를 사용하여 규칙을 추가합니다. 다음 샘플에서는 device.xml을 제외한 모든 공유 환경설정을 백업합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
     <include domain="sharedpref" path="."/>
     <exclude domain="sharedpref" path="device.xml"/>
    </full-backup-content>
    

백업에 필요한 기기 조건 정의

앱에서 기기에 민감한 정보를 저장하는 경우 사용자의 백업에 포함되는 앱의 데이터에 적용되는 조건을 지정할 수 있습니다. Android 9 (API 수준 28) 이상에서는 다음 조건을 추가할 수 있습니다.

  • clientSideEncryption: 사용자의 백업은 클라이언트 측의 보안 비밀을 사용하여 암호화됩니다. 이러한 암호화 양식은 사용자가 Android 9 이상에서 백업을 사용 설정하고 기기에 화면 잠금을 설정 (PIN, 패턴 또는 비밀번호)한 경우 Android 9 이상을 실행하는 기기에서 사용 설정됩니다.
  • deviceToDeviceTransfer: 사용자가 로컬 기기 간 전송 (예: Google Pixel)을 지원하는 다른 기기로 백업을 전송 중입니다.

개발 기기를 Android 9로 업그레이드했다면 업그레이드 후 데이터 백업을 사용 중지하고 다시 사용 설정해야 합니다. 왜냐하면 Android는 설정 또는 설정 마법사에서 사용자에게 알린 후에 클라이언트 측의 보안 비밀만 사용하여 백업을 암호화하기 때문입니다.

포함 조건을 선언하려면 requireFlags 속성을 백업 규칙 집합 내에서 선택한 값 또는 <include> 요소의 값으로 설정합니다.

backup_rules.xml

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <!-- App data isn't included in user's backup
         unless client-side encryption is enabled. -->
    <include domain="file" path="."
             requireFlags="clientSideEncryption" />
</full-backup-content>

앱에서 키-값 백업 시스템을 구현하거나 개발자가 직접 BackupAgent를 구현한다면 BackupDataOutput 객체의 전송 플래그 집합과 맞춤 백업 에이전트의 FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED 또는 FLAG_DEVICE_TO_DEVICE_TRANSFER 간에 비트별 비교를 실행하여 이러한 조건부 요구사항을 백업 로직에 적용할 수도 있습니다.

다음 코드 스니펫에서는 이러한 메서드의 사용 예를 보여줍니다.

Kotlin

class CustomBackupAgent : BackupAgent() {
    override fun onBackup(oldState: ParcelFileDescriptor?,
            data: BackupDataOutput?, newState: ParcelFileDescriptor?) {
        if (data != null) {
            if ((data.transportFlags and
                    FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
                // Client-side backup encryption is enabled.
            }

            if ((data.transportFlags and FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
                // Local device-to-device transfer is enabled.
            }
        }
    }

    // Implementation of onRestore() here.
}

Java

public class CustomBackupAgent extends BackupAgent {
    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {
        if ((data.getTransportFlags() &
                FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) != 0) {
            // Client-side backup encryption is enabled.
        }

        if ((data.getTransportFlags() &
                FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
            // Local device-to-device transfer is enabled.
        }
    }

    // Implementation of onRestore() here.
}

Android 12 이상에서 백업 제어

앱이 Android 12 (API 수준 31) 이상을 타겟팅하는 경우 이 섹션의 단계에 따라 Android 12 이상을 실행하는 기기에 백업되는 파일을 관리하세요.

  1. 다음 예와 같이 AndroidManifest.xml 파일에서 <application> 요소에 android:dataExtractionRules 속성을 추가합니다. 이 속성은 백업 규칙을 포함하는 XML 파일을 가리킵니다.

    <application ...
     android:dataExtractionRules="backup_rules.xml">
    </application>
    
  2. res/xml/ 디렉터리에 backup_rules.xml이라는 XML 파일을 만듭니다. 이 파일에 <include><exclude> 요소를 사용하여 규칙을 추가합니다. 다음 샘플에서는 device.xml을 제외한 모든 공유 환경설정을 백업합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <data-extraction-rules>
     <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
       <include domain="sharedpref" path="."/>
       <exclude domain="sharedpref" path="device.xml"/>
     </cloud-backup>
    </data-extraction-rules>
    

XML 구성 구문

구성 파일의 XML 구문은 앱이 타겟팅하고 실행하는 Android 버전에 따라 다릅니다.

Android 11 이하

Android 11 이하를 실행하는 기기의 백업을 제어하는 구성 파일에 다음 XML 구문을 사용합니다.

<full-backup-content>
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"
    requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] />
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string" />
</full-backup-content>

Android 12 이상

앱이 Android 12(API 수준 31) 이상을 타겟팅하는 경우 Android 12 이상을 실행하는 기기의 백업을 제어하는 구성 파일에 다음 XML 문법을 사용합니다.

<data-extraction-rules>
  <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </cloud-backup>
  <device-transfer>
    ...
    <include domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
    <exclude domain=["file" | "database" | "sharedpref" | "external" |
                     "root" | "device_file" | "device_database" |
                     "device_sharedpref" | "device_root" ] path="string"/>
    ...
  </device-transfer>
</data-extraction-rules>

구성의 각 섹션(<cloud-backup>, <device-transfer>)에는 특정 전송 유형에만 적용되는 규칙이 포함되어 있습니다. 이렇게 분리하면 예를 들어 D2D (기기 간) 전송 중에 파일이나 디렉터리를 계속 전송하면서 Google Drive 백업에서 제외할 수 있습니다. 이는 파일이 너무 커서 클라우드에 백업할 수는 없지만 문제없이 기기 간에 전송할 수 있는 경우에 유용합니다.

특정 백업 모드에 규칙이 없는 경우(예: <device-transfer> 섹션이 누락된 경우) 백업되는 파일 섹션에 설명된 대로 no-backupcache 디렉터리를 제외한 모든 콘텐츠에 이 모드가 완전히 사용 설정됩니다.

앱은 <cloud-backup> 섹션에서 disableIfNoEncryptionCapabilities 플래그를 설정하여 사용자에게 잠금 화면이 있는 경우와 같이 암호화할 수 있는 경우에만 백업이 이뤄지도록 할 수 있습니다. 이 제약조건을 설정하면 사용자의 기기에서 암호화를 지원할 수 없는 경우 백업이 클라우드로 전송되지 않지만 D2D 전송은 서버로 전송되지 않으므로 암호화를 지원하지 않는 기기에서도 계속 작동합니다.

include 및 exclude 요소에 관한 문법

<full-backup-content>, <cloud-backup><device-transfer> 태그(기기의 Android 버전 및 앱의 targetSDKVersion에 따라 다름) 내에서 <include><exclude> 요소를 정의할 수 있습니다.

<include>

백업할 파일 또는 폴더를 지정합니다. 기본적으로 자동 백업은 거의 모든 앱 파일을 포함합니다. <include> 요소를 지정하면 시스템은 더 이상 어떤 파일도 기본으로 포함하지 않고 지정된 파일만 백업합니다. 여러 파일을 포함하려면 여러 <include> 요소를 사용합니다.

Android 11 이하에서는 이 요소에 requireFlags 속성도 포함될 수 있습니다. 이 속성은 백업을 위한 조건부 요구사항을 정의하는 방법을 설명하는 섹션에서 자세히 설명합니다.

getCacheDir(), getCodeCacheDir() 또는 getNoBackupFilesDir()에서 반환된 디렉터리의 파일은 백업에 포함하려고 해도 항상 제외됩니다.

<exclude>

백업 중에 제외할 파일 또는 폴더를 지정합니다. 백업에서 일반적으로 제외되는 파일은 다음과 같습니다.

  • 서버에서 발행하거나 기기에서 생성한 기기별 식별자가 있는 파일. 예를 들어 Firebase 클라우드 메시징(FCM)은 사용자가 새 기기에 앱을 설치할 때마다 등록 토큰을 생성해야 합니다. 이전 등록 토큰이 복원되면 앱이 예기치 않게 동작할 수 있습니다.

  • 앱 디버깅과 관련된 파일.

  • 앱이 25MB의 백업 할당량을 초과하도록 하는 대용량 파일

<include><exclude> 요소는 다음 두 속성을 포함해야 합니다.

domain

리소스의 위치를 지정합니다. 이 속성의 유효한 값에는 다음 정보가 포함됩니다.

  • root: 이 앱에 속한 모든 비공개 파일이 저장된 파일 시스템의 디렉터리입니다.
  • file: getFilesDir()에서 반환한 디렉터리
  • database: getDatabasePath()에서 반환한 디렉터리 SQLiteOpenHelper를 사용하여 만든 데이터베이스가 여기 저장됩니다.
  • sharedpref: SharedPreferences가 저장된 디렉터리
  • external: getExternalFilesDir()에서 반환한 디렉터리
  • device_root: root과 같지만 기기 보호 저장소에 사용됩니다.
  • device_file: file과 같지만 기기 보호 저장소에 사용됩니다.
  • device_database: database과 같지만 기기 보호 저장소에 사용됩니다.
  • device_sharedpref: sharedpref와 같지만 기기 보호 저장소에 사용됩니다.
path

백업에 포함하거나 백업에서 제외할 파일 또는 폴더를 지정합니다. 다음 내용을 참고하세요.

  • 이 속성은 와일드 카드나 정규 표현식 구문을 지원하지 않습니다.
  • ./를 사용하여 현재 디렉터리를 참조할 수 있지만 보안상의 이유로 상위 디렉터리(예: .. 사용)는 참조할 수 없습니다.
  • 디렉터리를 지정하면 그 디렉터리와 반복되는 하위 디렉터리에 있는 모든 파일에 규칙이 적용됩니다.

BackupAgent 구현

자동 백업을 구현하는 앱은 BackupAgent를 구현하지 않아도 됩니다. 그러나 선택적으로 맞춤 BackupAgent를 구현할 수 있습니다. 일반적으로 이 작업을 하는 데는 두 가지 이유가 있습니다.

  • onRestoreFinished()onQuotaExceeded(long, long)와 같은 백업 이벤트의 알림을 수신하려는 경우 이러한 콜백 메서드는 앱이 실행 중이 아니어도 실행됩니다.

  • XML 규칙으로는 백업하려는 파일 집합을 쉽게 표현할 수 없습니다. 이러한 경우는 드물지만 onFullBackup(FullBackupDataOutput)를 재정의하여 원하는 파일을 저장하는 BackupAgent를 구현할 수 있습니다. 시스템의 기본 구현을 유지하려면 슈퍼클래스에서 super.onFullBackup()에 상응하는 메서드를 호출합니다.

BackupAgent를 구현하면 기본적으로 시스템은 앱에서 키/값 백업 및 복원을 실행할 것으로 예상합니다. 대신 파일 기반 자동 백업을 사용하려면 앱의 매니페스트에서 android:fullBackupOnly 속성을 true로 설정합니다.

자동 백업 및 복원 작업이 진행되는 동안 시스템은 앱을 제한 모드로 시작하여 앱이 충돌을 일으킬 수 있는 파일에 액세스하지 못하도록 하며 앱이 BackupAgent의 콜백 메서드를 실행할 수 있게 합니다. 이 제한 모드에서는 앱의 기본 활동이 자동으로 실행되지 않고 콘텐츠 제공자가 초기화되지 않으며 앱의 매니페스트에 선언된 서브클래스 대신 기본 클래스 Application가 인스턴스화됩니다.

BackupAgent는 키-값 백업에 사용되는 추상 메서드 onBackup()onRestore()를 구현해야 합니다. 키-값 백업을 실행하고 싶지 않다면 이러한 메서드의 구현을 비워 두면 됩니다.

자세한 내용은 BackupAgent 확장을 참고하세요.