Background Fetch는 새로운 콘텐츠를 다운로드하기 위해 백그라운드에서 주기적으로 앱을 깨우는 iOS 메커니즘입니다. 시스템은 사용자 행동을 분석하고 업데이트에 최적의 시간대를 선택합니다. Apple, 2026에 따르면 앱은 작업 수행에 30~120초가 주어지며, 이후 시스템이 프로세스를 일시 중단하거나 종료합니다.
핵심 사항
Background Fetch는 앱이 백그라운드에서 정기적으로 새 데이터를 수신할 수 있도록 하는 iOS API입니다. iOS 7에서 Background App Refresh 메커니즘과 함께 처음 도입되었습니다. 주요 목표는 사용자가 앱을 열 때 콘텐츠가 최신 상태여서 로딩을 기다릴 필요가 없도록 하는 것입니다.
푸시 알림은 서버에 의해 시작됩니다. 서버가 기기에 신호를 보내고 시스템이 앱을 깨울지 결정합니다. Background Fetch는 기기 사용 패턴을 기반으로 iOS 자체에 의해 시작됩니다. 푸시는 긴급 메시지에 더 적합하고, Fetch는 예약된 콘텐츠 업데이트(뉴스, 소셜 미디어 피드)에 적합합니다.
Background Fetch는 iOS의 여러 백그라운드 실행 메커니즘 중 하나입니다. BGAppRefreshTask(iOS 13+)는 동일한 작업을 수행하지만 더 유연한 스케줄링을 제공합니다. Background Modes(오디오, 위치)는 연속 작업을 위한 것입니다. Silent Push는 서버 시작 업데이트입니다. Fetch는 iOS 12 이하를 지원하는 프로젝트에 여전히 관련이 있습니다.
iOS는 머신 러닝 알고리즘을 사용하여 앱을 깨울 최적의 시간을 결정합니다. 시스템은 사용자가 일반적으로 언제 앱을 열고, 얼마나 오래 사용하며, 얼마나 자주 돌아오는지 분석합니다. 이 데이터를 기반으로 iOS는 Background Fetch 시간대를 계산합니다.
시스템이 앱을 깨우기로 결정하면 AppDelegate에서 application(_:performFetchWithCompletionHandler:) 메서드를 호출합니다. 앱은 최소한의 새 데이터를 로드하고 세 가지 상태 중 하나로 완료 핸들러를 호출해야 합니다: .newData(데이터 로드됨), .noData(새 데이터 없음) 또는 .failed(오류). 상태는 향후 깨우기 빈도에 영향을 줍니다.
.newData 상태는 시스템에 업데이트가 유용했음을 알립니다. iOS는 깨우기 빈도를 높일 수 있습니다. .noData는 데이터가 없음을 나타내며 빈도는 유지되거나 감소합니다. .failed는 문제를 나타내며 시스템은 배터리 절약을 위해 빈도를 줄입니다. 중요한 것은 .newData를 강제하는 것이 아니라 정직한 상태를 유지하는 것입니다.
| 상태 | 의미 | 영향 |
|---|---|---|
| .newData | 데이터가 성공적으로 로드됨 | 빈도가 증가할 수 있음 |
| .noData | 확인 결과 새 데이터 없음 | 빈도 유지 |
| .failed | 네트워크 또는 서버 오류 | 빈도 감소 |
Background Fetch를 활성화하려면 두 단계가 필요합니다: Xcode에서 기능을 활성화하고 코드에서 최소 간격을 설정합니다. 기능은 Target — Signing & Capabilities — Background Modes — Background Fetch 확인란에서 찾을 수 있습니다. 이 단계가 없으면 시스템이 앱을 깨우지 않습니다.
UIApplication.shared.setMinimumBackgroundFetchInterval 메서드는 Fetch 호출 사이의 최소 시간(초)을 설정합니다. 값 UIApplication.backgroundFetchIntervalMinimum(약 15분)은 시스템에 에너지 효율적인 범위 내에서 가능한 자주 앱을 깨우도록 지시합니다. application(_:didFinishLaunchingWithOptions:)에서 간격을 설정하는 것이 표준 관행입니다.
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey : Any]?
)-> Bool {
UIApplication.shared.setMinimumBackgroundFetchInterval(
UIApplication.backgroundFetchIntervalMinimum
)
return true
}
Xcode에서 Background Fetch를 활성화하면 Info.plist가 자동으로 업데이트되어 UIBackgroundModes 키에 fetch 값이 추가됩니다. 이는 필수 단계입니다. 이것이 없으면 앱이 performFetchWithCompletionHandler 호출을 받지 못합니다. P list Source 또는 Build Settings를 통해 확인할 수 있습니다.
뉴스 앱에 대한 완전한 Background Fetch 구현을 살펴보겠습니다. 구현에는 데이터 로딩, 캐싱 및 완료 핸들러 호출이 포함됩니다. 코드는 AppDelegate에서 실행됩니다. 시스템이 fetch를 호출하는 유일한 위치입니다.
func application(
_ application: UIApplication,
performFetchWithCompletionHandler handler: @escaping (UIBackgroundFetchResult) -> Void
) {
let url = URL(string: "https://api.example.com/latest")!
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
handler(.failed)
return
}
do {
let articles = try JSONDecoder().decode([Article].self, from: data)
cacheArticles(articles)
handler(articles.isEmpty ? .noData : .newData)
} catch {
handler(.failed)
}
}.resume()
}
Background Fetch를 통해 데이터를 로드한 후에는 로컬 저장소(CoreData, UserDefaults 또는 File Manager)에 저장해야 합니다. 앱을 열 때 데이터가 이미 사용 가능해야 합니다. 스레드 안전한 쓰기를 위해 백그라운드 컨텍스트와 함께 CoreData를 사용하세요. 저장 후 메인 스레드에서 UI를 업데이트합니다.
func cacheArticles(_ articles: [Article]) {
let container = NSPersistentContainer(name: "AppModel")
container.performBackgroundTask { context in
articles.forEach { article in
let entity = ArticleEntity(context: context)
entity.id = Int64(article.id)
entity.title = article.title
entity.body = article.body
}
try? context.save()
}
}
테스트를 위해 시뮬레이터를 사용하세요. Xcode에서 Debug — Simulate Background Fetch를 선택합니다. 실제 기기에서는 시스템이 fetch를 실행하기로 결정할 때까지 기다려야 합니다. 속도를 높이기 위해 최소 간격을 1분으로 설정할 수 있지만, 배터리가 부족하면 시스템이 이를 무시할 수 있습니다.
Background Fetch에는 앱 아키텍처를 설계할 때 고려해야 할 몇 가지 제한 사항이 있습니다. 가장 중요한 것은 시스템이 호출 빈도를 완전히 제어하며 개발자가 이를 보장할 수 없다는 것입니다. 최소 간격이 설정되어 있어도 시스템이 몇 시간 동안 fetch를 호출하지 않을 수 있습니다.
시스템은 작업 실행을 위해 앱에 제한된 시간(일반적으로 최대 30초)을 할당합니다. 앱이 해당 시간 내에 완료 핸들러를 호출하지 않으면 시스템이 강제로 프로세스를 종료하고 향후 깨우기 빈도를 줄입니다. 모든 네트워크 요청은 간결해야 하며 호출당 1~2개를 넘지 않아야 합니다.
iOS는 Background Fetch를 스케줄링할 때 배터리 잔량을 고려합니다. 충전량이 20% 미만이면 깨우기 빈도가 감소합니다. 저전력 모드가 활성화되면 시스템이 모든 앱의 백그라운드 업데이트를 완전히 비활성화할 수 있습니다. 사용자는 설정에서 특정 앱의 Background App Refresh를 비활성화할 수도 있습니다.
Background Fetch에서 시작된 URLSession은 표준 모드로 작동하며 백그라운드 세션을 지원하지 않습니다. 대용량 다운로드의 경우 백그라운드 구성이 있는 URLSession을 사용하세요. 시스템은 fetch 완료 후에도 다운로드를 계속하지만, 다음 깨우기까지 진행 상황이 추적되지 않습니다.
iOS 13부터 Apple은 BGTaskScheduler를 Background Fetch의 대체 도구로 권장합니다. BGTaskScheduler는 더 유연한 스케줄링, 두 가지 작업 유형(refresh 및 processing) 및 식별자를 통한 작업 등록을 제공합니다. 마이그레이션은 여러 단계로 구성되며 모든 새 프로젝트에 권장됩니다.
첫 번째 단계는 BGTaskSchedulerPermittedIdentifiers 키를 통해 Info.plist에서 작업 식별자를 정의하는 것입니다. 두 번째는 BGTaskScheduler.shared.register를 통해 AppDelegate에서 작업을 등록하는 것입니다. 세 번째는 performFetchWithCompletionHandler 호출을 register에 전달된 핸들러로 대체하는 것입니다. 네 번째는 작업을 스케줄링하기 위해 submit을 호출하는 것입니다.
// 이전 (Background Fetch)
UIApplication.shared.setMinimumBackgroundFetchInterval(
UIApplication.backgroundFetchIntervalMinimum
)
// 마이그레이션 후 (BGTaskScheduler)
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.example.refresh",
using: nil
) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
let request = BGAppRefreshTaskRequest(
identifier: "com.example.refresh"
)
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60)
try? BGTaskScheduler.shared.submit(request)
BGTaskScheduler는 더 많은 제어를 제공합니다: 장기 작업을 위한 BGProcessingTask(최대 10분), requiresNetworkConnectivity 및 requiresExternalPower를 통한 실행 조건, 정상적인 종료를 위한 만료 핸들러. 시스템은 앱 사용량도 분석하지만 개발자가 더 정확한 요구 사항을 설정할 수 있습니다.
앱이 iOS 12 이하를 지원하는 경우 Background Fetch가 정기적 업데이트를 위한 유일한 옵션입니다. BGTaskScheduler는 iOS 13+부터만 사용할 수 있습니다. 이 경우 래퍼를 사용하여 if #available(iOS 13, *)로 가용성을 확인하고 적절한 API를 호출합니다.
자주 묻는 질문
정확한 빈도는 문서화되어 있지 않으며 사용자 행동에 따라 다릅니다. 시스템이 사용자가 앱을 얼마나 자주 여는지 분석하고 그에 따라 빈도를 조정합니다. 평균적으로 활성 사용 시 fetch는 시간당 1~3회 호출될 수 있습니다. 드물게 사용하는 경우 하루 1~2회입니다.
세 가지 조건을 확인하세요: Background Fetch 기능이 Xcode에서 활성화되어 있는지, minimumBackgroundFetchInterval이 설정되어 있는지, 사용자가 설정에서 앱의 Background App Refresh를 비활성화하지 않았는지 확인합니다. 또한 기기가 저전력 모드가 아니고 배터리 잔량이 20% 이상인지 확인하세요.
Background Fetch는 이전 API(iOS 7)이고, BGAppRefreshTask는 새 API(iOS 13+)입니다. BGAppRefreshTask는 만료 핸들러, 재스케줄링 기능 및 상태 확인 등 더 많은 제어를 제공합니다. Background Fetch는 구현이 더 간단하지만 유연성이 떨어집니다. Apple은 새 프로젝트에 BGAppRefreshTask를 사용할 것을 권장합니다.
권장되지 않습니다. Background Fetch는 시간 제한이 있습니다(최대 30초). 대용량 다운로드의 경우 백그라운드 구성이 있는 URLSession을 사용하세요. 시스템은 fetch 완료 후에도 다운로드를 계속합니다. 대안으로 BGProcessingTask(iOS 13+)가 있으며 최대 10분과 충전 조건을 허용합니다.
네, 각 깨우기는 프로세서 전원 켜기, 네트워크 스택 초기화 및 데이터 로딩에 에너지를 소비합니다. iOS는 영향을 최소화하기 위해 빈도를 최적화합니다. 올바른 구현(새 데이터만 로드, 빠른 완료 핸들러 호출)으로 배터리 영향은 최소화됩니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.