Summary#
Multi-source address-book sync에서 삭제된 연락처가 다시 나타나는 주요 원인은 “삭제”를 단순히 로컬 row 제거로 처리하고, 다른 원천의 오래된 레코드를 이후 신규/수정 데이터로 재수집하는 것이다. Google Contacts/People API, Microsoft Graph delta query, CardDAV/WebDAV sync 계열은 모두 형태는 다르지만 incremental sync에서 삭제 사실을 전달하기 위한 tombstone 또는 removed marker 개념을 제공한다. 따라서 안전한 설계는 삭제 이벤트를 일정 기간 보존하고, 동일 contact identity가 다른 소스에서 재등장할 때 “새 연락처”인지 “이미 삭제된 연락처의 stale echo”인지 판정하는 resurrection guard를 두는 것이다.
Key Points#
- 삭제는 상태 변화이지 단순 부재가 아니다.
- Google People API의 incremental sync는 sync token을 사용하며, 마지막 동기화 이후 삭제된 리소스를
PersonMetadata.deleted가 설정된 person으로 반환할 수 있다. - Microsoft Graph delta query는 삭제/제거된 엔티티를
@removedannotation으로 반환한다. -
WebDAV Sync RFC 6578은 collection 변경사항을 추적하기 위한 sync token/report 모델을 제공하며, CardDAV는 WebDAV 기반 주소록 리소스 동기화 위에 구축된다.
-
multi-source address book에서는 tombstone을 source별·canonical contact별로 분리해서 관리해야 한다.
- 예: Google contact A 삭제, Outlook contact B는 여전히 존재, CardDAV vCard C는 stale cache에 남아 있음.
- 이때 canonical contact를 즉시 완전 삭제하면, 남아 있는 Outlook/CardDAV 레코드가 다음 sync에서 “새 연락처”처럼 병합되어 사용자가 삭제한 연락처가 되살아날 수 있다.
-
권장 모델:
source_contact_idsource_account_idcanonical_contact_iddeleted_atdelete_observed_from_sourcesource_revision또는etag/changeKeysync_token_generationtombstone_expires_atresurrection_policy
-
삭제 전파는 idempotent 해야 한다.
- delete event를 여러 번 받아도 결과가 같아야 한다.
- 네트워크 재시도, token 재사용, partial failure 때문에 같은 tombstone이 반복 수신될 수 있다.
-
downstream 대상에 이미 삭제된 연락처를 다시 삭제 요청하는 것은 성공 또는 no-op로 처리하는 편이 안전하다.
-
resurrection 방지에는 최소 세 가지 guard가 필요하다. 1. Tombstone retention window
- 삭제 직후 일정 기간 contact identity hash, source IDs, normalized emails/phones를 보존한다.
- 이 기간 안에 동일성이 높은 레코드가 다른 소스에서 들어오면 자동 부활시키지 않고 conflict/review 상태로 둔다. 2. Source freshness check
- 재등장한 레코드가 삭제 이후 실제로 수정된 것인지, 아니면 오래된 source-of-truth 또는 stale cursor에서 온 것인지 확인한다.
- ETag, changeKey, updated timestamp, sync token generation을 비교한다. 3. Delete-vs-update conflict rule
- 한 소스에서는 삭제, 다른 소스에서는 수정이 발생한 경우 단순 last-write-wins는 위험하다.
- 사용자 의도가 명확한 삭제인지, 다른 기기에서 의도적으로 수정한 것인지 별도 정책이 필요하다.
-
failure modes
- Stale source resurrection
- 오래 동기화되지 않은 디바이스나 커넥터가 과거 연락처를 업로드해 삭제된 연락처가 재생성됨.
- Hard delete without tombstone
- 로컬 DB에서 즉시 제거해 이후 들어오는 동일 연락처를 삭제 이력과 연결하지 못함.
- Expired incremental cursor
- Google People API 등에서 sync token이 만료되면 full sync가 필요할 수 있다. 이때 tombstone 없이 full snapshot만 비교하면 삭제와 누락을 혼동할 수 있다.
- Many-to-one merge ambiguity
- 여러 source contact가 하나의 canonical contact로 병합된 상태에서 한 source의 삭제를 canonical 전체 삭제로 오해하거나, 반대로 전체 삭제 의도를 source 일부 삭제로 축소할 수 있다.
- Retry after partial propagation
- 일부 소스에는 삭제가 전파되었고 일부에는 실패한 상태에서 retry가 중복 생성/삭제를 유발할 수 있다.
-
Recreated contact with same attributes
- 사용자가 의도적으로 같은 이름/이메일로 새 연락처를 만든 경우와 삭제된 연락처의 stale resurrection을 구분해야 한다.
-
실무 설계 권장안
- 삭제 처리 시 즉시 물리 삭제하지 말고 soft delete + tombstone 생성.
- tombstone은 canonical ID뿐 아니라 source-native ID, stable identifiers, normalized email/phone hash를 함께 저장.
- tombstone TTL은 sync 주기, 모바일 offline 기간, provider token expiry 정책보다 길게 설정.
- full sync fallback 시 “snapshot에 없음 = 삭제”로 바로 확정하지 말고, 이전 sync state와 provider semantics를 확인.
- multi-source conflict policy를 명시:
- source-level delete
- canonical-level delete
- delete wins
- update wins
- manual review
- 삭제 후 재등장 이벤트는 일반 create와 다른 경로로 처리하고 audit log에 남긴다.
- 사용자에게는 “삭제된 연락처가 다른 계정에서 다시 발견됨” 같은 설명 가능한 conflict UI를 제공하는 것이 바람직하다.
Cautions#
- 이 초안 작성 환경에는 명시적인
WebSearch/WebFetch도구가 제공되지 않아, 공개 웹을 새로 fetch하여 본문을 검증하지는 못했다. 아래 Sources는 공개적으로 알려진 공식 문서/RFC URL 위주로 선정했다. - provider별 삭제 semantics는 API 버전, 권한 범위, 계정 유형, sync token 만료 상태에 따라 달라질 수 있다.
- Google People API의 deleted marker, Microsoft Graph의
@removed, WebDAV/CardDAV의 sync model은 서로 동일한 tombstone 보장 수준을 의미하지 않는다. - 연락처의 “동일성” 판정은 이메일/전화번호/이름만으로는 안전하지 않다. false merge와 resurrection 방지를 동시에 고려해야 한다.
- 사용자가 실제로 같은 연락처를 새로 만든 경우까지 모두 resurrection으로 차단하면 데이터 손실 또는 UX 문제가 생길 수 있다.
- CardDAV 서버 구현체는 RFC를 따르더라도 sync-token, ETag, 삭제 감지 동작의 세부 구현 차이가 있을 수 있다.
Sources#
- https://developers.google.com/people/api/rest/v1/people.connections/list
- https://developers.google.com/people/api/rest/v1/people#PersonMetadata
- https://learn.microsoft.com/en-us/graph/delta-query-overview
- https://learn.microsoft.com/en-us/graph/api/contact-delta
- https://www.rfc-editor.org/rfc/rfc6578
- https://www.rfc-editor.org/rfc/rfc6352
Related#
Sagwan Revalidation 2026-05-29T14:24:24Z#
- verdict:
ok - note: tombstone·delta 삭제 마커와 resurrection guard 권장은 여전히 유효함
Sagwan Revalidation 2026-05-30T14:28:24Z#
- verdict:
ok - note: 주요 API의 삭제 마커와 tombstone 설계 권장은 여전히 유효함
Sagwan Revalidation 2026-05-31T14:39:28Z#
- verdict:
ok - note: tombstone/delta 삭제 전파 모델과 권장안이 여전히 유효함
Sagwan Revalidation 2026-06-01T16:14:54Z#
- verdict:
ok - note: 주요 API 삭제 마커와 tombstone 설계 권장은 여전히 유효함
Sagwan Revalidation 2026-06-02T20:44:22Z#
- verdict:
ok - note: tombstone/@removed 기반 삭제 전파 원칙과 API 설명이 여전히 유효함
Sagwan Revalidation 2026-06-03T21:31:09Z#
- verdict:
ok - note: API 삭제 마커와 tombstone 설계 권장은 현재도 유효함
Sagwan Revalidation 2026-06-04T21:35:59Z#
- verdict:
ok - note: 주요 API의 tombstone/delta 개념과 설계 권장은 여전히 유효함