백그라운드에서 작업을 돌릴 수 있는 타입에대해 알아보려합니다


백그라운드 전환 이후에도 작업을 계속 수행하고 시스템은 UI를 통해 진행 상황을 표시를 지원합니다
- 버튼 클릭이나 다른 제스처처럼 항상 명확한 사용자 행동으로 시작됩니다
- 각 작업은 즉각적이고 명확한 목표를 가지고 있습니다 (파일 내보내기 SNS 콘텐츠 게시 연결된 액세서리 업데이트 등)
- 이러한 작업은 측정 가능한 진행률을 가지고 있으며 작업이 완료됐을 때 무엇을 의미하는지 알 수 있습니다
시스템은 리소스 부족과 같은 런타임 상황에 따라 백그라운드 작업을 갑작스럽게 종료할 수 있습니다.
구현 시에는 이 작업이 준수하는 ProgressReporting 프로토콜을 사용하여 진행 상황을 보고해야 합니다.
리소스가 부족해지면 시스템은 진행 상황이 거의 없거나 전혀 없는 작업의 종료를 우선적으로 처리합니다
BGContinuedProcessingTask
- 👍 즉시 시작 / 진행률 UI 자동 / 사용자가 기다리는 작업이라 시스템이 우호적(런타임 넉넉) / GPU·CPU·네트워크 사용 가능
- 👎 iOS 26+ 전용 / 반드시 포그라운드 사용자 액션에서 제출(서버·백그라운드 트리거 ❌) / progress 필수 / 무한은 아님(자원 압박 시 expirationHandler로 회수) / 사용자에게 보이는 작업에만 적합
기존에 쓰던 백그라운드 방식과 비교해볼까요?

BGProcessingTask
- 👍 수 분 이상 긴 작업 / "충전 중·네트워크 필요" 조건 지정 가능 / 무거운 유지보수에 최적
- 👎 실행 시점을 시스템이 결정(즉시성 없음, 보통 밤/충전) / UI 없음 / 사용자 인지 못 함
BGAppRefreshTask
- 👍 사용 패턴 학습해 "열어볼 만한 때" 갱신 / 콘텐츠 신선도 유지에 적합
- 👎 매우 짧음(~30s) / 시점·실행 보장 안 됨 / UI 없음
- Background Push Notifications: 서버가 원할때 푸시로 백그라운드 업데이트 진행, BGAppRefreshTask의 푸시버전
beginBackgroundTask (구형)
- 👍 모든 버전 / 간단 / 즉시
- 👎 수십 초 / 긴 작업 불가 / UI 없음 → continued가 사실상 현대적 대체재
Background URLSession
- 👍 앱이 종료돼도 전송 지속, 시스템이 재시도/관리
- 👎 순수 다운/업로드 전용 — 임의 연산은 못 함
플로우
- info.plist정의 - UIBackgroundModes키 [processing] BGTaskSchedulerPermittedIdentifiers: [식별자 identifier]
Permitted background task scheduler identifiers 배열에 새 값을 추가하고 앱 번들 ID로 시작되도록 합니다.
정적인 식별자 외에도 동적 접미사를 지원하는 와일드카드 형식을 지원합니다 - BGTaskScheduler.shared.register 로 id, 큐, 작업 등록
- BGContinuedProcessingTaskRequest 생성 후 BGTaskScheduler.shared.submit 제출하면 작업시작
진행 속도가 예상보다 느릴 경우 시스템은 사용자에게 작업을 계속할지 묻게 됩니다 - 필요한 작업 마지막에 setTaskCompleted로 작업완료 알림
키워드
BGContinuedProcessingTaskRequest
init - 제출요청 id, 시스템 UI에 최초노출될 타이틀 지정
request.strategy
실행시 전략으로 2가지가 있습니다
- queue(기본): 본적으로 지속적 처리 작업을 즉시 실행할 수 없을 경우 시스템이 queue에 작업을 추가합니다
즉시 실행 불가시 큐 사용해서 가능할때까지 대기합니다 - fail: 해당 작업이 당장 시작되어야만 유용할때.
작업을 queue에 넣는 대신 즉시 실행할 수 없으면 제출을 실패하게 할 수 있습니다
이를 통해 앱은 즉각적인 피드백을 받고 상황을 적절히 처리할 수 있습니다
BGContinuedProcessingTask
.progress.totalUnitCount
현재 진행 상황에 대한 추적 대상 작업 단위의 총 수
.progress.completedUnitCount
시스템UI, Live Activity, Dynamic Island용 진행률 갱신
.updateTitle(, subtitle: )
시스템UI, Live Activity, Dynamic Island용 제목 갱신
.expirationHandler
작업의 백그라운드 시간이 만료되기 직전에 호출되는 핸들러입니다.
정리/중단 된경우 처리
.setTaskCompleted(success: )
작업종료를 시스템에 알림(성공/실패)
예시코드
// 등록코드
nonisolated func registerHandler() {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: Self.taskIdentifier,
using: Self.workQueue
) { [self] task in
guard let task = task as? BGContinuedProcessingTask else {
task.setTaskCompleted(success: false)
return
}
// workQueue 위에서 동기적으로 작업을 수행한다.
performWork(task)
}
}
// 사용자가 시작버튼 (Ex: 업로드 버튼)
func start() {
// 최초 시스템 UI 노출 타이틀지정
let request = BGContinuedProcessingTaskRequest(
identifier: Self.taskIdentifier,
title: "긴 작업 진행 중",
subtitle: "백그라운드로 전환해도 계속 진행됩니다"
)
// 즉시 실행할 수 없으면 큐잉 (다른 옵션: .fail = 즉시 불가 시 제출 실패)
request.strategy = .queue
do {
try BGTaskScheduler.shared.submit(request)
} catch {
statusMessage = "작업 제출 실패: \(error.localizedDescription)"
}
}
// 작업코드
nonisolated private func performWork(_ task: BGContinuedProcessingTask) {
let total: Int64 = 600
// 진행률 보고는 BGContinuedProcessingTask 에서 필수.
task.progress.totalUnitCount = total
// 만료(시스템 회수/강제 종료) 시 루프를 중단시키기 위한 플래그.
let isCancelled = Locked(false)
task.expirationHandler = {
isCancelled.set(true)
}
publishStatus("작업 시작")
var step: Int64 = 0
while step < total {
if isCancelled.get() {
task.setTaskCompleted(success: false)
return
}
// 1초 단위의 더미 작업 시뮬레이션
Thread.sleep(forTimeInterval: 1.0)
step += 1
// 시스템 UI(Live Activity / Dynamic Island)용 진행률 + 제목 갱신
task.progress.completedUnitCount = step
task.updateTitle("긴 작업 진행 중", subtitle: "\(step)/\(total)초 완료")
}
task.setTaskCompleted(success: true)
// 로컬 푸시 알림
sendCompletionNotification()
}
스크린샷




'iyOmSd > Title: Swift' 카테고리의 다른 글
| [Swift] Protocol Buffer (Protobuf) (0) | 2026.04.28 |
|---|---|
| [iOS] AI 기본 개념부터 온디바이스까지 정리해보기 (1) | 2026.03.31 |
| [Swift] Core Image Filter (0) | 2026.01.27 |
| [Swift] Vision FaceDetect (0) | 2025.11.29 |
| [Swift] Screen Time API(DeviceActivity) (0) | 2025.10.27 |