← 기술 지식

기술 지식 / 웹·모바일 / iOS

멀티 씬 문서의 저장과 충돌 복구

종료 콜백에 의존하지 않는 저장, 씬별 UI와 공용 문서 소유, 중복 저장·역순 완료·동시 편집의 버전 계약을 설명합니다.

모바일 · 원리·구현·운영
기술 지식 트리

이 노트는 멀티 씬 앱에서 화면 복원 상태와 공용 문서의 권위를 분리하고, 중단·중복·역순 완료·동시 편집을 저장 계약으로 다루는 방법을 설명합니다. 먼저 언제든 중단될 수 있는 실행 모델을 놓고, 그 위에 변경 ID와 기준 버전 검사를 배치합니다.

종료 알림 유실과 조기 저장 시점

사용자가 문서를 편집한 뒤 앱이 시스템 종료나 강제 종료를 맞으면 종료 직전 콜백이 실행되지 않아 마지막 변경을 저장하지 못할 수 있습니다. 그래서 중요한 변경은 종료 시점까지 미루지 않고 더 이른 시점에 저장하며, 백그라운드 진입은 남은 저장을 마무리할 추가 기회로 사용합니다. 백그라운드 실행 허용 시간이 무제한 완료 보장을 뜻하지는 않으므로, 그 시간만 믿고 마지막 저장을 맡기지 않습니다.

멀티 씬에서는 한 프로세스 안의 여러 창이 서로 다른 활성 상태를 가질 수 있습니다. 한 씬이 배경으로 갔다고 모든 씬이 같이 멈추는 것도 아닙니다. 씬별 화면 복원 상태와 여러 씬이 공유하는 문서 상태의 소유자를 나누어야 합니다. 예를 들어 씬 A의 선택 문서·스크롤 위치는 A에 귀속되지만, 본문 v7과 저장 순서는 공용 저장소가 권위입니다. A가 백그라운드에 갔다고 B의 최신 편집을 덮어쓸 권한이 생기지 않으며, 각 저장 요청에 documentId·expectedVersion·changeId를 포함해야 합니다.

씬별 상태와 공용 문서 권위의 분리

상태 대표 소유자 예
씬 UI 씬별 저장 선택 문서·스크롤·패널 위치
문서 본문 공용 문서 저장소 텍스트·내용 버전
계정 자격 적절한 자격 저장소 로그인 세션·토큰
동기화 진행 공용 작업 상태 업로드 위치·불확정 결과
두 씬은 하나의 문서 저장소를 공유합니다씬 A: 기준 문서 v7 · 편집 X. 씬 B: 기준 문서 v7 · 편집 Y. 공용 문서 저장소: version 조건 · 충돌 정책, 한 문서의 저장 순서. 복구 가능한 저장본: 본문과 버전을 함께 보존기준 v7 저장기준 v7 저장조건부 확정씬 A기준 문서 v7 · 편집 X씬 B기준 문서 v7 · 편집 Y공용 문서 저장소version 조건 · 충돌 정책한 문서의 저장 순서복구 가능한 저장본본문과 버전을 함께 보존
두 씬은 하나의 문서 저장소를 공유합니다 화살표는 저장 요청입니다. 각 씬의 UI 상태는 독립적이고 문서 변경은 공통 저장소가 기준 버전과 함께 확정합니다.
그림을 글로 읽기
  • 씬 A: 기준 문서 v7 · 편집 X
  • 씬 B: 기준 문서 v7 · 편집 Y
  • 공용 문서 저장소: version 조건 · 충돌 정책 · 한 문서의 저장 순서
  • 복구 가능한 저장본: 본문과 버전을 함께 보존
  1. 씬 A → 공용 문서 저장소: 기준 v7 저장
  2. 씬 B → 공용 문서 저장소: 기준 v7 저장
  3. 공용 문서 저장소 → 복구 가능한 저장본: 조건부 확정

한 씬에서 마지막으로 완료됐다는 이유로 다른 씬의 새 본문을 덮으면 안 됩니다. 요청 시작 순서와 디스크 쓰기 완료 순서는 다를 수 있습니다.

동일 버전 중복과 기준 버전 편집 충돌

SceneDelegate와 SwiftUI scenePhase가 동일한 변경에 대해 버전 8 저장을 동시에 요청했다고 합시다. 저장소가 changeId를 이미 완료된 요청으로 기록해 두면 두 번째 요청은 본문을 다시 쓰지 않고 기록된 결과를 반환할 수 있습니다.

하지만 씬 A와 B가 각각 기준 v7에서 서로 다른 본문을 만들었다면, 두 요청의 버전 숫자가 모두 8이라는 이유로 중복으로 취급하면 안 됩니다. 문서 ID는 무엇을 저장하는지, 기준 버전은 어떤 상태에서 편집했는지, 변경 ID는 같은 요청의 재전송인지, 내용은 무엇이 달라졌는지를 각각 비교해야 합니다.

commitEdit(documentId, expectedVersion, changeId, newBody):
    in_one_storage_transaction:
        if changeId was already committed: return recorded_result
        current = load_for_update(documentId)
        if current.version != expectedVersion:
            return conflict(current)
        store(body=newBody, version=current.version+1)
        record(changeId, resultVersion=current.version+1)
    return committed_result

A가 v7에서 v8을 확정한 뒤 B가 기준 v7로 저장을 시도하면, 저장소의 현재 버전 8과 B의 expectedVersion 7이 달라져 충돌로 끝나야 합니다. 두 변경이 서로 다른 필드라면 도메인 규칙으로 병합할 수 있지만, 같은 문단 수정·삭제·권리 변경은 자동 병합이 의미를 바꿀 수 있어 사용자 판단이나 도메인 규칙이 필요합니다. B의 옛 본문을 버전 숫자만 8로 바꿔 재전송하면 이 비교를 우회하므로 허용하지 않습니다.

저장 단위와 복구 범위의 세분화

변경 시점 저장이나 짧은 debounce는 종료 직전만 저장하는 것보다 유실 범위를 줄입니다. debounce 기간의 손실을 허용할 수 있는지 명시하고 백그라운드로 갈 때 가능한 저장을 마무리합니다. 백그라운드 실행 허용 시간은 무제한 완료 보장이 아닙니다.

큰 파일을 제자리 덮어쓰다 중단되면 기존 복구본까지 손상될 수 있습니다. 새 파일을 완성·검증한 뒤 교체하고 내용 버전과 완료 정보를 일치시킵니다. 원자 교체의 가시성과 전원 장애 내구성은 파일시스템 계약에 맞게 구분합니다. 저장 실패를 UI에 성공으로 표시하지 않고 다음 실행에서 마지막 유효본과 미완료 작업을 복구할 수 있게 합니다.

저장 버전 순서와 최신 상태 보호

v8 저장이 느린 사이 v9 저장이 먼저 완료되고, 뒤늦게 끝난 v8이 같은 파일 경로를 덮으면 파일의 본문이 최신 버전에서 옛 버전으로 역행합니다. 문서별 저장을 직렬화하거나 v8·v9처럼 버전별 임시 파일을 만든 뒤, 권위 포인터가 현재 버전일 때만 갱신하도록 해야 합니다. UI의 savedVersion도 네트워크 응답이 먼저 왔다는 이유가 아니라 실제로 저장소가 확정한 버전을 표시해야 합니다.

업로드 응답 유실은 로컬 저장 실패와 다릅니다. 원격에는 이미 반영됐을 수 있으므로 작업 ID와 결과 조회를 유지해야 합니다. 앱이 다시 활성화되면 현재 문서와 동기화 상태를 읽고, 재전송·충돌·완료를 구분합니다. 진단 표에는 로컬 본문 버전, 서버 권위 버전, changeId 상태, 마지막 시도 시각, 원격 결과 조회 가능 여부를 남깁니다. “응답을 못 받음”은 저장 실패가 아니라 확정 여부 미상일 수 있으므로 무조건 새 변경으로 재전송하지 않습니다.

씬별 동작 차이를 반영한 복구 시험

두 씬에서 같은 문서를 열고 한쪽만 백그라운드로 보내며 동시에 저장합니다. 같은 changeId 중복은 하나로, 다른 기준 편집은 충돌 또는 의도한 병합으로 처리되어야 합니다. 입력 직후·파일 작성 중·교체 직전·원격 성공 응답 전 중단을 시험합니다.

실제 iOS 백그라운드 API와 문서 저장 프레임워크의 세부 지원은 대상 버전에서 확인해야 합니다. 이 노트의 목적은 특정 콜백 횟수를 암기하는 것이 아니라 어떤 순간에 중단돼도 마지막 유효 상태와 남은 작업을 설명할 수 있게 만드는 것입니다. 실제 검증은 입력 직후·write 중·교체 직전·응답 유실·두 씬 동시 편집을 각각 재현하고, 재시작 후 마지막 유효본과 미완료 작업이 구분되는지 확인하는 방식으로 끝내야 합니다.

후속·관련 개념

함께 읽을 문서

전체 기술 지식
선택 연습 · 관련 질문 3개

질문은 이해를 확인하는 보조 자료입니다. 학습 경로와 문서의 범위는 질문 수와 독립적입니다.