iOS 앱이 백그라운드 상태로 전환된 후에도 타이머를 계속 실행해야 하는 경우가 있습니다. 이럴 때 Apple은 beginBackgroundTaskWithExpirationHandler 메서드를 제공합니다. 자세한 내용은 Apple 공식 문서에서 확인할 수 있습니다.
이 문서에서는 해당 메서드를 활용해 앱이 백그라운드에 있을 때 타이머가 동작하도록 구현하는 방법을 단계별로 알아보겠습니다.
구현 단계
1단계 — 프로젝트 생성
Xcode를 열고 Single View Application 템플릿으로 새 프로젝트를 생성한 뒤, 프로젝트 이름을 BackgroundTimer로 지정합니다.
2단계 — AppDelegate에 백그라운드 작업 등록
AppDelegate.swift 파일을 연 다음, applicationDidEnterBackground 메서드 안에 아래 코드를 작성합니다.
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: {
UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
})
_ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.doSomething), userInfo: nil, repeats: true)이 코드는 앱이 백그라운드로 진입하는 시점에 백그라운드 작업을 시작하고, 만료 핸들러(expiration handler)를 통해 시스템이 작업을 종료하기 전에 정리할 수 있도록 합니다. 그리고 1초 간격으로 반복 실행되는 타이머를 예약합니다.
3단계 — doSomething() 함수 작성
타이머가 호출할 새로운 함수를 작성합니다.
@objc func doSomething() {
print("I'm running")
}완성된 코드
최종적으로 코드는 아래와 같은 형태가 됩니다.
func applicationDidEnterBackground(_ application: UIApplication) {
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: {
UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
})
_ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.doSomething), userInfo: nil, repeats: true)
}
@objc func doSomething() {
print("I'm running")
}앱 실행 및 테스트
앱을 빌드하고 실행한 뒤 홈 버튼을 눌러 앱을 백그라운드로 전환해 보세요. 앱이 백그라운드 상태로 진입하는 순간 콘솔에 "I'm running"이라는 로그가 출력되기 시작합니다.
다만 주의할 점이 있습니다. Apple 공식 문서에 명시되어 있고 실제 테스트 결과로도 확인되었듯이, 일반적인 방식으로는 백그라운드에서 타이머를 최대 약 3분까지만 실행할 수 있습니다.
직접 확인해 보려면 앱을 백그라운드로 전환한 후 약 3분간 기다려 보세요. 3분이 지나면 "I'm running" 로그가 더 이상 출력되지 않습니다. 이후 앱을 다시 포그라운드로 가져오면 로그 출력이 재개되는 것을 확인할 수 있습니다.

만약 3분 이상 장시간 백그라운드 작업이 필요하다면, 위치 업데이트·오디오 재생·VoIP 같은 특정 백그라운드 모드(background modes)를 사용하거나, iOS 13 이상에서 제공되는 BGTaskScheduler 프레임워크를 검토하는 것이 좋습니다.