NSFileCoordinator — iOS 파일 액세스 조정

저자: IT Sectr 게시일: 2026-07-11 읽는 시간: 7 분

NSFileCoordinator는 여러 스레드, 프로세스 또는 확장 프로그램이 동시에 작동할 때 안전한 파일 액세스를 보장하는 iOS 및 macOS의 Foundation 클래스입니다. Apple Developer Documentation, 2024에 따르면, NSFileCoordinator는 파일 읽기 및 쓰기 중 경합 상태를 방지하여 한 프로세스가 데이터를 수정하는 동안 다른 프로세스가 데이터를 읽지 않도록 보장합니다. 코디네이터는 iCloud Drive, File Provider Extension 및 모든 멀티스레드 파일 작업에서 사용됩니다.

주요 내용

  • NSFileCoordinator — 여러 스레드 및 프로세스에서 안전한 파일 액세스를 위한 클래스
  • 조정 인텐트(읽기/쓰기 인텐트)는 실행 전에 작업 유형을 선언합니다
  • 경합 상태 방지 — 병렬 액세스에서 코디네이터의 주요 작업
  • File Provider 지원 — iCloud Drive 및 확장 프로그램 파일 작업 시 코디네이터 필수
  • NSFilePresenter — 다른 프로세스의 파일 변경 알림을 받기 위한 프로토콜

NSFileCoordinator란?

NSFileCoordinator는 Apple이 iOS 5 및 macOS 10.7 Lion에서 도입한 운영 체제 수준의 파일 액세스 동기화 메커니즘입니다. 기존 잠금(NSLock, pthread_mutex)과 달리 코디네이터는 파일 시스템 수준에서 작동하며 동일한 애플리케이션의 스레드 간뿐만 아니라 다른 프로세스 간의 액세스도 조정할 수 있습니다.

NSFileCoordinator의 필요성은 iOS의 Sandbox 아키텍처에서 발생합니다. 각 프로세스(애플리케이션, 확장 프로그램, 시스템 서비스)는 자체 파일 액세스 권한을 가진 격리된 환경에서 실행됩니다. 여러 프로세스가 동시에 동일한 파일을 읽고 쓰려고 할 때(예: iCloud Drive 동기화 중), 코디네이터가 없으면 경합 상태가 발생합니다. 프로세스 A가 파일을 읽는 동안 프로세스 B가 이미 파일을 부분적으로 덮어쓴 상황입니다.

WWDC 2023에 따르면 Apple은 Ubiquity 컨테이너(iCloud Drive) 및 File Provider Extension 작업 시 모든 파일 작업에 NSFileCoordinator를 사용할 것을 강력히 권장합니다. 조정을 무시하는 것은 iOS 애플리케이션에서 데이터 손상 및 재현 불가능한 버그의 일반적인 원인 중 하나입니다.

조정 인텐트 유형

조정 인텐트(NSFileCoordinator.ReadingIntent / WritingIntent)는 스레드 또는 프로세스가 수행하려는 작업 유형을 선언하는 객체입니다. 코디네이터는 이러한 인텐트를 사용하여 액세스 순서를 결정하고 충돌을 해결합니다.

인텐트 유형설명사용 시기
ReadingIntent변경 없는 파일 읽기문서 열기, 데이터 로드
WritingIntent내용 변경 가능성이 있는 쓰기문서 저장, 편집
ReadingIntent(URL, options: .withoutChanges)변경 추적 없는 읽기빠른 내용 미리보기
WritingIntent(URL, options: .contentIndependentMetadataOnly)메타데이터만 수정날짜 또는 속성 업데이트
WritingIntent(URL, options: .forDeleting)파일 삭제사용자의 문서 삭제

조정 규칙: 여러 동시 읽기가 허용됩니다(활성 쓰기가 없는 경우). 쓰기는 배타적입니다 — 쓰기 작업 중에는 읽기나 쓰기가 허용되지 않습니다. 이는 Readers-Writer 잠금 모델을 따르지만 launchd 및 XPC를 통한 프로세스 간 조정에 대한 추가 지원이 있습니다.

중요한 차이점: NSFileCoordinator는 일반 NSData 또는 FileManager를 통한 파일 액세스를 방지하지 않습니다 — 명시적으로 조정 블록에 래핑된 작업만 조정합니다. 다른 스레드가 코디네이터 없이 직접 파일에 액세스하면 코디네이터가 방지하도록 설계된 바로 그 경합 상태가 발생합니다.

NSFileCoordinator 작동: 코드 예제

기본 패턴 NSFileCoordinator 사용법은 세 단계로 구성됩니다: 코디네이터 인스턴스 생성, 인텐트 선언(읽기 또는 쓰기), 조정 블록 내에서 작업 실행. 코디네이터는 다른 코디네이터가 동일한 파일로 동시에 작업하지 않음을 보장합니다.

swift
import Foundation

let coordinator = NSFileCoordinator()
let fileURL = getDocumentURL()

// Safe reading
let readIntent = NSFileCoordinator
    .ReadingIntent(url: fileURL)
var content: Data?
var readError: NSError?

coordinator.coordinate(with: readIntent) { error in
    if let error = error {
        readError = error
        return
    }
    content = try? Data(contentsOf: fileURL)
}

// Safe writing
let writeIntent = NSFileCoordinator
    .WritingIntent(url: fileURL)

coordinator.coordinate(with: writeIntent) { error in
    guard error == nil else { return }
    do {
        try newData.write(to: fileURL)
    } catch {
        Logger.storage.error(
            "Write failed: \(error)"
        )
    }
}

배치 작업 — 코디네이터는 인텐트 배열을 사용하여 단일 작업으로 여러 파일을 처리할 수 있습니다. 이는 파일 세트를 단일 트랜잭션으로 이동, 복사 또는 삭제하는 데 편리합니다. 하나의 인텐트를 수행할 수 없으면 전체 작업이 오류와 함께 취소됩니다.

swift
let coordinator = NSFileCoordinator()
let readIntent = NSFileCoordinator
    .ReadingIntent(url: sourceURL)
let writeIntent = NSFileCoordinator
    .WritingIntent(url: destURL)

coordinator.coordinate(
    with: [readIntent, writeIntent]
) { error in
    try? FileManager.default
        .copyItem(at: sourceURL, to: destURL)
}

비동기 조정 — iOS 15부터 NSFileCoordinator는 완료 핸들러와 함께 비동기 메서드를 지원하여 호출 스레드를 차단하지 않고 조정을 수행할 수 있습니다. 이는 UI 스레드에서 중요하며, 조정을 위한 동기 대기로 인해 인터페이스가 몇 초 동안 멈출 수 있습니다.

NSFilePresenter 프로토콜 및 알림

NSFilePresenter는 NSFileCoordinator가 조정하는 파일의 변경 사항에 대한 알림을 받기 위해 객체가 구현하는 프로토콜입니다. 애플리케이션이 다른 프로세스에 의해 변경될 수 있는 파일의 내용을 표시하는 경우(예: iCloud Drive가 새 버전을 동기화), NSFilePresenter를 구현하면 적시에 인터페이스를 업데이트할 수 있습니다.

swift
class DocumentPresenter: NSFilePresenter {
    let presentedItemURL: URL?
    let presentedItemOperationQueue: OperationQueue

    init(url: URL) {
        presentedItemURL = url
        presentedItemOperationQueue = OperationQueue()
    }

    func presentedItemDidChange() {
        DispatchQueue.main.async {
            NotificationCenter.default
                .post(name: .documentDidChange,
                      object: self)
        }
    }

    func presentedItemDidMove(to newURL: URL) {
        Logger.storage.info(
            "File moved to: \(newURL.lastPathComponent)"
        )
    }

    func accommodatePresentedItemDeletion(
        completionHandler: @escaping (Error?) -> Void
    ) {
        Logger.storage.warn("File deleted externally")
        completionHandler(nil)
    }
}

프로토콜 메서드: presentedItemDidChange는 파일 내용이 변경될 때 호출되며, presentedItemDidMove(to:) — 파일 이동 후, accommodatePresentedItemDeletion — 다른 프로세스에 의한 파일 삭제 전(애플리케이션이 파일을 정상적으로 닫을 수 있도록 함). 추가로 프로토콜은 presentedItemDidGainVersion: 및 presentedItemDidLoseVersion:을 통한 버전 관리를 지원합니다.

중요: NSFilePresenter는 NSFileCoordinator.addFilePresenter:를 통해 시스템에 등록되어야 합니다. 등록 없이는 알림이 전달되지 않습니다. 등록은 애플리케이션 시작 시 한 번 수행되며 프리젠터가 다시 생성될 때 재등록이 필요하지 않습니다.

파일 조정 모범 사례

항상 코디네이터를 사용하세요 Ubiquity 컨테이너(iCloud Drive) 및 확장 프로그램이 액세스할 수 있는 디렉토리의 파일에 대해. 애플리케이션이 현재 단일 스레드이더라도 향후 업데이트나 시스템 변경으로 인해 병렬 액세스가 추가될 수 있으며, 조정 부족은 찾기 어려운 버그로 이어집니다.

조정 블록 내 시간을 최소화하세요. 블록이 실행되는 동안 다른 프로세스는 파일에 액세스할 수 없습니다. 블록 내에서 장기 작업(복잡한 데이터 처리, 네트워크 요청)은 전체 파일 액세스 시스템을 차단합니다. 블록 내에서는 데이터 읽기 또는 쓰기만 수행하고 처리는 블록 외부에서 수행하세요.

데드락을 피하세요: 동일한 파일에 대해 다른 코디네이터의 블록 내에서 코디네이터를 호출하지 마세요 — 상호 데드락이 발생합니다. 중첩 호출 대신 배치 작업(인텐트 배열)을 사용하세요. 중첩이 필요한 경우 다른 큐나 다른 URL을 사용하세요.

objc.io(2024)에 따르면 NSFileCoordinator 작업 시 일반적인 오류는 다음과 같습니다: 완료 핸들러에서 오류 처리 부족(불완전한 작업으로 이어짐); 쓰기만 조정하고 읽기는 조정하지 않음; UI 스레드에서 오래된 동기 API 사용; iCloud Drive 작업 시 NSFilePresenter 프로토콜 무시. 마지막 오류가 가장 교활합니다: 애플리케이션은 파일이 이미 수정되었다는 것을 인지하지 못하고 오래된 데이터를 표시합니다.

자주 묻는 질문

NSFileCoordinator란 무엇인가요?

NSFileCoordinator는 여러 스레드 또는 프로세스에서 안전한 파일 액세스를 위한 Foundation 클래스입니다. 파일 시스템 수준에서 읽기 및 쓰기 작업을 조정하여 경합 상태를 방지합니다.

NSFileCoordinator와 NSLock의 차이점은 무엇인가요?

NSLock은 단일 프로세스 내에서만(스레드 간) 작동합니다. NSFileCoordinator는 iCloud Drive 동기화 및 File Provider Extension을 포함하여 다른 프로세스와 확장 프로그램 간의 액세스를 조정합니다.

iCloud Drive에 NSFileCoordinator를 반드시 사용해야 하나요?

, Apple은 Ubiquity 컨테이너의 모든 파일 작업에 NSFileCoordinator를 사용할 것을 강력히 권장합니다. 코디네이터 없이는 기기 간 동기화 중 데이터 손상 및 File Provider Extension과의 충돌이 발생할 수 있습니다.

NSFilePresenter란 무엇인가요?

NSFilePresenter는 파일 변경 알림을 받기 위한 프로토콜입니다. 애플리케이션이 다른 프로세스의 변경에 반응할 수 있게 합니다: 수정 시 UI 업데이트, 이동 처리, 파일 삭제 준비 등.

NSFileCoordinator는 어떤 인텐트 유형을 지원하나요?

다섯 가지 유형: ReadingIntent(읽기), WritingIntent(쓰기), .withoutChanges가 있는 ReadingIntent(추적 없는 읽기), .contentIndependentMetadataOnly가 있는 WritingIntent(메타데이터만), .forDeleting이 있는 WritingIntent(삭제). 각각 파일 액세스 수준을 정의합니다.

요약

  • NSFileCoordinator — 스레드, 프로세스 및 확장 프로그램에서 안전한 파일 액세스를 위한 시스템 메커니즘
  • 조정 인텐트(읽기/쓰기)는 실행 전에 작업 유형을 선언합니다
  • 읽기는 병렬 허용, 쓰기는 배타적(Readers-Writer 모델)
  • NSFilePresenter — 다른 프로세스의 파일 변경 알림을 위한 프로토콜
  • iCloud Drive 및 File Provider는 데이터 손상 방지를 위해 필수 조정 필요
  • 조정 블록 내 시간 최소화 — 장기 작업은 다른 프로세스의 액세스를 차단합니다
  • 데드락은 배치 작업 및 중첩 코디네이터 호출 방지로 예방됩니다

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기