제품 소식

Android에서 연락처를 추가하고 수정하는 더 안정적인 방법

읽는 데 6분 소요
록사나 알리아바디 워커의 프로필 보기
Roxanna Aliabadi Walker Android 제품 관리자

변경되는 사항

향후 출시될 Android 버전을 타겟팅하는 앱은 더 이상 WRITE_CONTACTS 권한을 사용하여 연락처에 직접 쓸 수 없습니다. 대신 표준 연락처 인텐트 (ACTION_INSERT, ACTION_EDIT, ACTION_INSERT_OR_EDIT)를 사용할 수 있습니다. 전체 참조 구현은 인텐트를 사용하여 연락처를 수정하는 방법에 관한 개발자 가이드를 참고하세요. 

향후 Android 출시 버전을 실행하는 기기에서는 이 세 가지 연락처 인텐트가 일관되게 작동하며 권한이 전혀 필요하지 않습니다. 앱이 향후 Android 출시 이상을 타겟팅하고 연락처에 직접 쓰기를 시도하면 쓰기가 거부되고 SecurityException 또는 권한 거부가 발생합니다. 연락처를 만들고 수정하기 위해 광범위한 액세스 권한이 필요한 소수의 앱을 위해 Android 17 QPR2 (2026년 4분기)에 새로운 특별 앱 액세스 권한인 MANAGE_CONTACTS가 도입됩니다. Google Play는 오늘 MANAGE_CONTACTS를 포함한 연락처 액세스에 관한 업데이트된 가이드라인을 게시합니다.

이 작업을 수행하는 이유

현재 앱에서 연락처를 하나라도 저장해야 하는 경우 WRITE_CONTACTS를 요청해야 할 수 있습니다. 하지만 이 권한은 광범위한 액세스 권한을 부여하므로 앱이 사용자 상호작용 없이도 백그라운드에서 기기 전반의 연락처를 광범위하게 변경할 수 있습니다. 대부분의 앱에는 이러한 광범위한 권한이 필요하지 않습니다.

대안이 존재하지만, 생태계 전반에서 더 표준화되어야 한다는 의견이 있었습니다. 이전에는 연락처 인텐트가 기기마다 다르게 작동했습니다. 일부 편집기에서는 연락처 사진과 같이 전달한 데이터를 삭제했습니다. 일부 기기에서는 뒤로 버튼을 누르면 사용자가 의도하지 않았는데도 연락처가 저장되거나 '새 연락처 만들기' 옵션을 찾기 어려웠습니다. 따라서 허가를 요청하는 것이 합리적인 선택이었습니다. Google은 향후 Android 버전에서 이러한 모든 문제를 해결하고 있으며, 이 버전을 실행하는 기기가 동일한 표준을 따르도록 요구하고 있습니다.

대신 사용할 항목

연락처 추가 또는 수정: 연락처 인텐트 사용

ACTION_INSERT, ACTION_EDIT, ACTION_INSERT_OR_EDIT 인텐트를 사용하면 시스템이 깔끔하고 표준화된 연락처 편집기 환경을 제공하여 복잡한 작업을 처리합니다. 새 항목을 위한 빠른 하프 시트 양식을 열거나 사용자가 기존 연락처를 쉽게 검색하고 정보를 추가할 수 있습니다. 사용자는 앱에 직접 쓰기 권한이 없어도 이를 전체 페이지 편집기로 원활하게 확장하여 더 많은 세부정보를 입력할 수 있습니다. 아래에서 임시 UX 모의를 확인하세요. 

Figure01_01_Quick_Insert_Half_Sheet_Prefilled.png
스크린샷 2 - 제목: 새 연락처 만들기 전체 시트 모의: 아바타 선택기, 이름, 전화번호, 이메일 입력란이 있는 전체 화면 연락처 편집기를 보여주는 임시 Android 사용자 인터페이스의 스크린샷입니다. 디자인에 'UX not Final'이라는 라벨이 지정되어 있습니다.

그림 1: 새 연락처 만들기  *최종 UX 아님*

Figure02_01_Add_To_Existing_0_Search_State_Half_Sheet.png
스크린샷 2 - 제목: '기존 연락처에 정보 추가'의 전체 시트 모의: 아바타 선택기, 이름, 전화번호, 이메일 입력란이 있는 전체 화면 연락처 편집기를 보여주는 임시 Android 사용자 인터페이스의 스크린샷입니다. 전체 페이지 디자인에는 보조 필드를 위한 단계적 공개 칩이 있습니다. 디자인에 'UX not Final'이라는 라벨이 지정되어 있습니다.

그림 2: 기존 연락처에 정보 추가 *UX는 최종 버전이 아님*


참고: 기기 제조업체마다 OS 스타일에 맞게 사용자 환경을 수정할 수 있지만 동작은 동일하게 유지됩니다.


인텐트와 함께 Extras라고 하는 선택적 데이터 페이로드를 전달하여 생성 프로세스를 더욱 간소화할 수 있습니다.

  • EXTRA_ACCOUNT는 연락처가 저장되는 계정을 제안하므로 앱에서 연락처를 동기화하는 경우에 유용합니다. 이 추가 기능은 이미 존재했지만 기기에 따라 지원이 달랐습니다. 향후 Android 출시부터 지원이 기기 전반에서 표준화됩니다.
  • EXTRA_PHOTO_URI는 사진을 전달하여 연락처 사진을 자동 입력합니다. 편집기가 URI 읽기 권한을 처리합니다. 이는 곧 출시될 Android 버전에 새로 추가되는 기능이며 생태계 전반에서 지원될 예정입니다.

이전: WRITE_CONTACTS로 직접 작성 (앱이 향후 Android 출시를 타겟팅하면 SecurityException 또는 권한 거부가 발생함)

 

// Requires android.permission.WRITE_CONTACTS
fun saveContactDirectly(context: Context, name: String, phone: String, account: Account) {
    val ops = arrayListOf(
        ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type)
            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name)
            .build(),
        ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
            .withValue(
                ContactsContract.Data.MIMETYPE,
                ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
            )
            .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
            .build(),
        ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
            .withValue(
                ContactsContract.Data.MIMETYPE,
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
            )
            .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
            .build()
    )
    context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
}

 

 

변경 후: 연락처 편집기 열기 (권한 필요 없음)

 

fun saveContactWithEditor(
    context: Context,
    name: String,
    phone: String,
    account: Account,
    photoUri: Uri
) {
    val intent = Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI).apply {
        putExtra(ContactsContract.Intents.Insert.NAME, name)
        putExtra(ContactsContract.Intents.Insert.PHONE, phone)
        // Suggest which account the contact is saved to
        putExtra(ContactsContract.Intents.Insert.EXTRA_ACCOUNT, account)
        // New in the upcoming Android release: pre-fill the contact photo
        putExtra(ContactsContract.Intents.Insert.EXTRA_PHOTO_URI, photoUri)
        clipData = ClipData.newRawUri("", photoUri)
        addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    }
    context.startActivity(intent)
}

 

이전: 기존 연락처 직접 업데이트

 

// Requires android.permission.WRITE_CONTACTS
fun addPhoneDirectly(context: Context, rawContactId: Long, phone: String) {
    val values = ContentValues().apply {
        put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
        put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
        put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
    }
    context.contentResolver.insert(ContactsContract.Data.CONTENT_URI, values)
}

After: 사용자가 업데이트할 연락처를 선택하거나 새 연락처를 만들 수 있음

fun addPhoneWithEditor(context: Context, phone: String) {
    val intent = Intent(Intent.ACTION_INSERT_OR_EDIT).apply {
        type = ContactsContract.Contacts.CONTENT_ITEM_TYPE
        putExtra(ContactsContract.Intents.Insert.PHONE, phone)
    }
    context.startActivity(intent)
}

업데이트할 연락처를 이미 알고 있는 경우 해당 연락처의 URI와 함께 ACTION_EDIT를 사용합니다.

fun editKnownContact(context: Context, contactUri: Uri, phone: String) {
    val intent = Intent(Intent.ACTION_EDIT, contactUri).apply {
        putExtra(ContactsContract.Intents.Insert.PHONE, phone)
    }
    context.startActivity(intent)
}

 

연락처 선택: 연락처 선택 도구 사용

사용자가 선택한 연락처만 읽어야 하는 경우 Android 17부터 사용할 수 있는 연락처 선택 도구를 사용하세요. 권한이 필요하지 않습니다.

통화 및 메시지 앱: 사용자 디렉터리 사용

일부 앱은 연락처에 '통화…' 또는 '메시지…' 작업을 추가하여 사용자가 전화 앱이나 연락처 앱에서 통화나 채팅을 시작할 수 있도록 합니다. 현재 앱에서 사용자의 연락처에 추가 항목을 작성하여 이 작업을 실행하는 경우 Android QPR2 (2026년 4분기)에 제공되는 사용자 디렉터리로 이동하세요. 이는 사용자의 연락처를 수정하지 않고도 앱에서 사용자가 서로 연락할 수 있는 방법을 게시하는 새로운 시스템 디렉터리입니다.

앱 이전 방법의 예

이러한 대안이 실제로 어떻게 작동하는지 보여주기 위해 다양한 유형의 앱이 연락처 액세스에 접근하는 방식의 몇 가지 예시를 소개합니다.

앱 유형 예시 (일부)권장 이전 경로
소셜, P2P 결제, 차량 공유 앱앱에서 사용자가 친구를 찾거나, 청구서를 분할하거나, 여행 상태를 공유할 수 있는 경우 연락처 권한이 전혀 필요하지 않습니다. 연락처 선택 도구를 사용하여 일회성 연락처 선택을 수행하고, 사용자가 프로필에서 '연락처에 저장'을 탭하면 EXTRA_PHOTO_URI를 사용하여 ACTION_INSERT를 실행합니다.
명함 스캐너 및 이벤트 네트워킹 앱앱에서 배지 또는 QR 코드를 스캔하고 새 연락처를 저장하거나 기존 동료의 항목에 직장 전화번호를 추가하는 경우 ACTION_INSERT 또는 ACTION_INSERT_OR_EDIT를 사용합니다. 표준화된 하프 시트 편집기는 파싱된 필드 (이름, 회사, 전화번호, 이메일, 사진)를 자동 입력하므로 사용자는 백그라운드 권한을 부여하지 않고도 탭 한 번으로 확인하고 저장할 수 있습니다.
VoIP 통화 및 메시지 앱WRITE_CONTACTS에 맞춤 '통화…' 또는 '메시지…' 행을 사용자의 주소록에 삽입하도록 요청하는 대신, 사용자 디렉터리를 통해 연결 가능성 메타데이터를 게시하고 사용자가 채팅 대화목록에서 새 연락처를 추가할 때 ACTION_INSERT를 사용하세요.
엔터프라이즈 CRM 및 클라우드 동기화 앱앱이 클라우드 또는 회사 계정과 지속적인 양방향 백그라운드 연락처 동기화를 실행하는 경우(모든 레코드에 대해 인텐트 UI를 사용자에게 표시하는 것이 불가능함) 앱은 MANAGE_CONTACTS 를 선언할 수 있습니다.

확인할 변경사항

  • 맞춤 데이터 유형은 편집기에서 지원되지 않습니다. 표준 ContactsContract.CommonDataKinds 유형이 아닌 MIME 유형이 있는 Insert.DATA 행을 전달하면 해당 MIME 유형은 편집기에서 자동으로 무시됩니다.
  • SHOW_OR_CREATE_CONTACT 은 시스템 편집기에서 처리되지 않습니다. 기기와 함께 제공되는 연락처 앱은 계속해서 이를 처리할 수 있습니다. 여러 기기에서 일관된 동작을 위해 ACTION_INSERT_OR_EDIT를 사용하세요.
  • 기본적으로 쓰기가 실패합니다. 출시 예정인 Android 버전을 타겟팅하면 MANAGE_CONTACTS 없이 직접 쓰기 시 SecurityException or permission denial이 발생합니다. 테스트합니다.

MANAGE_CONTACTS이(가) 필요한가요?

그렇지 않을 수도 있습니다. 사용자의 요청에 따라 앱에서 연락처를 저장하거나 수정하는 경우 위의 인텐트가 적용되므로 권한이나 Play Console 선언이 필요하지 않습니다.

MANAGE_CONTACTS은 연락처 관리가 핵심 목적인 앱에서 인텐트가 충분하지 않은 경우에 사용됩니다. 예를 들면 다음과 같습니다.

앱이…MANAGE_CONTACTS이(가) 필요하신가요?
채팅, 명함 또는 주문에서 연락처를 저장합니다.아니요, ACTION_INSERT 사용
기존 연락처에 전화번호 또는 이메일을 추가합니다.아니요,ACTION_INSERT_OR_EDIT 또는 ACTION_EDIT 사용
사용자가 초대, 공유 또는 결제할 연락처를 선택할 수 있습니다.아니요,연락처 선택 도구를 사용합니다.
연락처에 통화 또는 메시지 작업을 추가합니다.아니요,사용자 디렉터리 사용
자체 브랜드 연락처 수정 화면이 있습니다.아니요. 맞춤 인터페이스만으로는 자격 요건을 충족하지 않습니다.
전용 연락처 관리자 또는 다이얼러 대체 앱입니다.예
주소록 항목을 일괄 업데이트하는 발신번호 표시 및 스팸 차단 앱입니다.예
백그라운드에서 연락처를 엔터프라이즈 또는 클라우드 계정과 동기화합니다.예
연락처 일괄 백업/복원 또는 기기 간 휴대전화 전송을 실행합니다.예
개별 연락처에 맞춤 벨소리를 설정합니다.예

작동 방식:

  • MANAGE_CONTACTS은 특별한 앱 액세스 권한입니다. 런타임 대화상자가 아닙니다. 사용자는 설정 > 특수 앱 액세스 > 연락처 관리에서 이 기능을 사용 설정합니다.
// Opens Settings > Apps > Special app access > Manage contacts
val intent = Intent(Settings.ACTION_MANAGE_CONTACTS, Uri.fromParts("package", packageName, null))
context.startActivity(intent)
  • 연락처, 계정, 사용자 디렉터리 데이터 읽기, 추가, 수정, 삭제를 다룹니다. READ_CONTACTS도 요청할 필요가 없습니다.
  • MANAGE_CONTACTS 권한을 사용하여 Google Play에 게시하려면 인텐트가 앱의 핵심 기능에 충분하지 않은 이유를 설명하는 선언을 Play Console에서 제출해야 합니다.

이전 단계

  • 연락처 쓰기를 찾습니다. 코드에서 WRITE_CONTACTS, ContactsContract.RawContacts.CONTENT_URI, ContactsContract.Data.CONTENT_URI, applyBatch(ContactsContract.AUTHORITY, …)를 검색합니다.
  • 사용자 주도 쓰기를 인텐트로 대체합니다. 새 연락처의 경우 ACTION_INSERT, 업데이트의 경우 ACTION_EDIT 또는 ACTION_INSERT_OR_EDIT입니다.
  • Insert.DATA에서 표준 데이터 유형만 사용합니다. 통화 또는 메시지 작업을 사용자 디렉터리로 이동합니다.
  • 위 표를 사용하여 MANAGE_CONTACTS가 정말로 필요한지 결정 합니다. 그렇다면 Play Console 선언을 계획하세요.
  • 코드 경로에 필요하지 않은 경우 매니페스트에서 WRITE_CONTACTS를 삭제 합니다.

타임라인

요일결과
2026년 10월 21일Google Play에서 MANAGE_CONTACTS 정책을 발표합니다.
2026년 (Android 17 분기별 플랫폼 출시 2)MANAGE_CONTACTS 권한을 사용할 수 있게 됨
2027 (예정된 Android 출시)WRITE_CONTACTS는 더 이상 향후 Android 출시 버전을 타겟팅하는 앱에 쓰기 액세스 권한을 부여하지 않습니다. 연락처 인텐트는 기기 전반에서 표준화됩니다.
2027년, 예정된 Android 출시 이후Play Console에서 MANAGE_CONTACTS을(를) 사용하는 앱에 선언을 제출하도록 요청함
2027년, 예정된 Android 출시 이후Play 정책 준수 필요

FAQ

  • 모든 앱에 영향을 미치나요?
    • WRITE_CONTACTS 지원 중단 변경사항은 예정된 Android 출시 이후 버전을 타겟팅하는 앱에만 적용됩니다. 이전 버전을 타겟팅하는 앱은 현재 동작을 유지하지만, 새로운 표준화된 연락처 편집기는 타겟 SDK와 관계없이 새 OS에서 실행되는 모든 앱에서 사용할 수 있습니다.
  • 앱에서 인텐트를 사용하여 연락처를 삭제할 수 있나요?
    • 아니요. 연락처를 삭제하는 인텐트는 없습니다. 사용자는 연락처 앱에서 연락처를 삭제합니다. MANAGE_CONTACTS 권한이 있는 앱은 연락처를 직접 삭제할 수 있습니다.
  • 이미 자체 연락처 수정 화면이 있습니다. 계속 사용할 수 있나요?
    • 앱이 MANAGE_CONTACTS 자격 요건을 충족하는 경우에만 해당됩니다. 맞춤 디자인을 유지하고 싶다는 이유만으로는 자격 요건을 충족하지 않습니다.
  • MANAGE_CONTACTS이 READ_CONTACTS를 대체하나요?
    • MANAGE_CONTACTS에는 읽기 액세스 권한이 포함되어 있으므로 둘 다 요청할 필요는 없지만, 연락처를 수정할 필요가 없는 많은 앱이 READ_CONTACTS에 적합합니다. 이러한 앱은 계속해서 READ_CONTACTS을 요청할 수 있습니다.
  • 이전 Android 버전을 사용하는 사용자는 어떻게 되나요?
    • 연락처 인텐트는 이전 버전에서도 작동하며 기기의 연락처 앱에서 처리됩니다. 대부분의 앱은 이러한 인텐트를 사용하여 모든 기기에서 잘 작동합니다. 앱이 최신 버전에서만 해결되는 특정 일관성 문제의 영향을 받는 경우 적절한 maxSdkVersion으로 범위가 지정된 매니페스트에 WRITE_CONTACTS 권한을 유지할 수 있습니다.
계속 읽기