Notification Service Extension — 푸시 알림 처리 작동 방식

저자: IT Sectr 게시일: 2026-06-16 읽는 시간: 9 분

Notification Service Extension은 푸시 알림을 수신 직후, 사용자에게 표시되기 전에 가로채는 iOS 확장 프로그램입니다. 이 확장 프로그램은 암호화된 페이로드를 해독하고, 미디어 파일을 다운로드하여 첨부하며, 알림 텍스트나 제목을 실시간으로 변경할 수 있습니다. Apple 개발자 문서(2025)에 따르면, 확장 프로그램을 활성화하려면 서버가 알림 속성에 mutable-content:1 키를 보내야 합니다. 이것이 UNNotificationServiceExtension을 실행하는 유일한 조건입니다.

핵심 내용

  • Notification Service Extension은 iOS 기기에서 사용자에게 표시되기 전에 푸시 알림을 수정합니다
  • 확장 프로그램 활성화를 위해서는 서버 알림 페이로드에 mutable-content:1 매개변수가 필요합니다
  • 주요 프로토콜은 UNNotificationServiceExtension이며, didReceive(_:withContentHandler:) 및 serviceExtensionTimeWillExpire() 메서드를 포함합니다
  • 확장 프로그램은 네트워크에서 미디어 첨부 파일을 다운로드하여 UNNotificationAttachment를 통해 알림에 첨부할 수 있습니다
  • 실행 시간이 제한되어 있습니다 — 시스템은 하나의 알림을 완전히 처리하는 데 약 30초를 할당합니다

Notification Service Extension이란

Notification Service Extension은 iOS의 앱 확장 프로그램으로, 기기 측에서 들어오는 푸시 알림을 가로채서 사용자가 보기 전에 콘텐츠를 수정할 수 있게 합니다. 이것은 표시가 아닌 콘텐츠를 처리하는 유일한 유형의 알림 확장 프로그램입니다.

Notification Content Extension과의 주요 차이점: Service Extension은 알림이 표시되기 전에 작동하며 제목, 본문, 사운드 파일 및 첨부 파일을 변경할 수 있습니다. Content Extension은 표시된 후에 작동하며 완성된 알림의 시각적 표현만 관리합니다. 이 두 확장 프로그램은 함께 작동할 수 있습니다: Service Extension이 이미지를 다운로드하고 Content Extension이 사용자 정의 인터페이스에 표시합니다.

확장 프로그램은 aps 사전에 mutable-content:1 속성이 있는 푸시 알림을 수신하면 자동으로 활성화됩니다. iOS는 백그라운드에서 확장 프로그램을 시작하고 원래 UNNotificationRequest를 전달한 다음 표시할 수정된 버전을 기다립니다.

푸시 알림 즉시 처리

UNNotificationServiceExtension은 원래 콘텐츠와 함께 전체 UNNotificationRequest를 수신합니다. 확장 프로그램은 UNNotificationContent의 모든 필드(title, subtitle, body, userInfo, attachments, sound)를 수정할 수 있습니다. 변경 사항은 알림이 표시되기 전에 적용됩니다.

일반적인 사용 시나리오

콘텐츠 해독 — 푸시 알림에 암호화된 페이로드가 포함된 경우 확장 프로그램이 표시 전에 해독합니다. 미디어 다운로드 — 이미지나 비디오를 알림에 첨부합니다. 현지화 — 기기의 지역 설정에 맞게 알림 텍스트를 조정합니다. 데이터 강화 — 로컬 저장소나 캐시에서 추가 정보를 추가합니다.

Apple에 따르면, 앱에서 가장 일반적인 시나리오는 리치 미디어 알림을 위한 이미지 다운로드입니다. 서버가 페이로드에 이미지 URL을 보내고, 확장 프로그램이 임시 디렉토리에 다운로드하여 UNNotificationAttachment를 생성하며, 시스템이 표준 또는 사용자 정의 인터페이스에 표시합니다.

텍스트 및 제목 수정

확장 프로그램은 알림 텍스트를 완전히 다시 쓰거나, 제목을 바꾸거나, 부제목을 추가할 수 있습니다. 예를 들어, 메신저 앱이 암호화된 알림을 받아 확장 프로그램에서 해독하고 읽을 수 있는 텍스트를 표시할 수 있습니다. 또는 뉴스 앱이 표시 전에 부제목에 뉴스 카테고리를 추가할 수 있습니다.

swift
override func didReceive(
    _ request: UNNotificationRequest,
    withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
    let content = request.content.mutableCopy()
        as! UNMutableNotificationContent
    if let imageURL = content.userInfo["media-url"]
        as? String {
        downloadAndAttach(imageURL: imageURL,
            content: content,
            handler: contentHandler)
    }
}

UNNotificationServiceExtension 프로토콜

UNNotificationServiceExtension은 Service Extension이 상속받는 기본 클래스입니다. 이 클래스는 두 가지 생명주기 메서드를 정의합니다: didReceive(_:withContentHandler:) — 주요 처리 메서드, 그리고 serviceExtensionTimeWillExpire() — 타임아웃 핸들러입니다.

didReceive:withContentHandler: 메서드

didReceive(_:withContentHandler:)는 알림을 수신할 때 호출됩니다. 확장 프로그램은 UNNotificationRequest와 수정된 UNMutableNotificationContent로 호출해야 하는 contentHandler 클로저를 받습니다. 확장 프로그램은 contentHandler를 호출해야 합니다 — 호출하지 않으면 iOS는 타임아웃 후 원래 알림을 표시합니다.

중요: 확장 프로그램은 한 번에 하나의 알림만 처리할 수 있습니다. 여러 알림이 동시에 도착하면 iOS는 각각에 대해 별도의 확장 프로그램 인스턴스를 만듭니다. 순차 처리를 위해 전역 상태를 사용할 수 없습니다.

serviceExtensionTimeWillExpire: 메서드

serviceExtensionTimeWillExpire()는 남은 실행 시간이 거의 다 되면 시스템에 의해 호출됩니다. 이 메서드에서는 즉시 contentHandler를 현재 준비된 콘텐츠로 호출해야 합니다 — 미디어 파일 다운로드가 완료되지 않았더라도 마찬가지입니다. 이 메서드에서 contentHandler를 호출하지 않으면 iOS가 원래 알림을 표시합니다.

이 메서드에서는 최소한 허용 가능한 콘텐츠를 저장하는 것이 좋습니다 — 예를 들어, 텍스트와 제목이 있지만 다운로드가 제때 완료되지 않은 이미지가 없는 알림입니다.

암호화 및 미디어 첨부 파일

UNNotificationAttachment는 미디어 파일을 알림에 첨부하기 위해 확장 프로그램이 생성하는 객체입니다. 확장 프로그램은 네트워크에서 파일을 다운로드하고, 임시 디렉토리에 저장하며, 콘텐츠 유형을 지정하여 UNNotificationAttachment를 생성합니다.

다운로드한 파일에서 첨부 파일 만들기

UNNotificationAttachment는 init(identifier:url:options:) 초기화 프로그램을 사용하여 생성됩니다. URL은 확장 프로그램이 액세스할 수 있는 임시 디렉토리의 로컬 파일을 가리켜야 합니다. 생성 후 첨부 파일은 UNMutableNotificationContent의 attachments 배열에 추가됩니다.

Apple은 다운로드에 백그라운드 구성을 사용한 URLSession을 권장합니다 — 표준 URLSession을 사용하면 다운로드가 스레드를 차단하고 30초 제한 시간을 소비합니다. 백그라운드 URLSession은 확장 프로그램이 종료된 후에도 다운로드를 계속하며, 결과는 다음 실행 시 사용할 수 있습니다.

암호화된 페이로드 해독

서버가 암호화된 알림을 보내는 경우, 확장 프로그램은 contentHandler를 호출하기 전에 페이로드를 해독해야 합니다. 해독에는 일반적으로 Keychain 또는 App Group에서 키를 요청하고, CommonCrypto를 통해 해독하며, 알림의 body 또는 userInfo를 교체하는 과정이 포함됩니다. 해독 오류가 발생한 경우, 원래 콘텐츠로 contentHandler를 호출해야 합니다 — 사용자가 읽을 수 없더라도 알림이 도착했다는 것을 최소한 확인할 수 있도록 합니다.

swift
func downloadAndAttach(
    imageURL: String,
    content: UNMutableNotificationContent,
    handler: @escaping (UNNotificationContent) -> Void
) {
    let task = URLSession.shared.dataTask(with:
        URL(string: imageURL)!) { data, _, _ in
        let url = FileManager.default
            .temporaryDirectory
            .appendingPathComponent("image.jpg")
        try? data?.write(to: url)
        let attachment = try? UNNotificationAttachment(
            identifier: "image", url: url)
        content.attachments = [attachment].compactMap { $0 }
        handler(content)
    }
    task.resume()
}

타임아웃 및 폴백 메커니즘

Notification Service Extension은 엄격한 시간 제약 내에서 작동합니다. iOS는 고정된 실행 시간을 할당합니다 — 활성화 후 약 30초입니다. 이 시간 내에 확장 프로그램이 contentHandler를 호출하지 않으면 시스템이 강제로 프로세스를 종료하고 변경되지 않은 원래 알림을 표시합니다.

그레이스풀 디그라데이션 전략

다단계 폴백을 구현하는 것이 좋습니다: 먼저 미디어 다운로드를 시도하고, 성공하면 전체 콘텐츠로 contentHandler를 호출합니다; 실패하면 텍스트만 포함하고 미디어 없이 contentHandler를 호출합니다; 심각한 오류가 발생하면 원래 콘텐츠를 전달합니다. 이 접근 방식은 사용자가 빈 화면이 아닌 항상 알림을 볼 수 있도록 보장합니다.

Apple에 따르면, 타임아웃의 가장 흔한 원인은 느린 연결에서 대용량 미디어 파일 다운로드입니다. 위험을 줄이기 위해 서버에서 이미지 크기를 최적화하는 것이 좋습니다 — 전체 해상도 대신 최대 300KB의 미리보기를 보냅니다. 전체 크기 이미지는 앱을 열 때 다운로드해야 합니다.

성능 모니터링

확장 프로그램 타임아웃 및 오류를 추적하기 위해 os_log를 사용하여 통합 로깅 시스템에 진단 메시지를 기록할 수 있습니다. 확장 프로그램에서 직접 파일 로깅은 어렵지만, os_log를 통해 개발자 기기의 Console.app에서 성능 분석이 가능합니다. Apple은 각 didReceive 호출에 메트릭(다운로드 시간, 파일 크기, 작업 결과)을 추가할 것을 권장합니다.

swift
override func serviceExtensionTimeWillExpire() {
    let fallback = bestEffortContent as?
        UNMutableNotificationContent
        ?? request.content.mutableCopy()
        as! UNMutableNotificationContent
    contentHandler(fallback)
}

자주 묻는 질문

서버가 Notification Service Extension을 어떻게 활성화하나요?

서버가 푸시 알림의 aps 사전에 mutable-content:1 키를 추가합니다. 이 매개변수가 없으면 시스템이 확장 프로그램을 무시하고 표준 알림을 표시합니다.

mutable-content 없이 확장 프로그램을 사용할 수 있나요?

아니요. mutable-content:1은 Service Extension 활성화의 필수 조건입니다. 키가 없거나 0으로 설정된 경우, 확장 프로그램을 호출하지 않고 알림이 표시됩니다.

30초 제한을 초과하면 어떻게 되나요?

iOS가 강제로 확장 프로그램을 종료하고 변경되지 않은 원래 알림을 표시합니다. 이를 방지하려면 최소한 허용 가능한 콘텐츠로 serviceExtensionTimeWillExpire()를 구현하세요.

확장 프로그램에 암호화 키를 어떻게 전달하나요?

App Group(공유 UserDefaults 또는 파일) 또는 앱과 확장 프로그램 간에 공유 액세스가 가능한 Keychain을 통해 전달합니다. 알림 페이로드에 키를 직접 전달하는 것은 안전하지 않습니다.

Service Extension에서 몇 개의 미디어 파일을 첨부할 수 있나요?

알림당 최대 4개의 첨부 파일, 각각 최대 50MB입니다. 첨부 파일의 총 크기는 다운로드 시간에 영향을 미칩니다 — 파일이 많을수록 타임아웃 위험이 높아집니다.

요약

  • Notification Service Extension은 기기에서 푸시 알림을 표시하기 전에 텍스트, 제목 및 미디어 첨부 파일을 수정합니다
  • 활성화를 위해서는 aps 사전에 mutable-content:1 키가 필요합니다 — 이것이 없으면 확장 프로그램이 실행되지 않습니다
  • 주요 프로토콜 UNNotificationServiceExtension은 처리를 위한 didReceive 및 serviceExtensionTimeWillExpire 메서드를 정의합니다
  • 확장 프로그램은 네트워크에서 미디어를 다운로드하고, 페이로드를 해독하며, 알림에 최대 4개의 첨부 파일을 추가할 수 있습니다
  • 실행 시간은 약 30초로 제한됩니다 — 초과 시 iOS가 원래 알림을 표시합니다
  • 빈 알림을 방지하기 위해 다단계 폴백을 사용한 그레이스풀 디그라데이션 전략이 권장됩니다

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

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

프로젝트 논의

더 읽어보기