-
WKURLSchemeHandleriOS 2025. 11. 9. 08:37
안녕하세요. 그린입니다 🍏
오늘은 iOS 11에서 도입된 WKURLSchemeHandler에 대해 깊이 있게 살펴보려고 합니다.

WKWebView에서 커스텀 URL Scheme을 처리하는 방법을 찾고 계셨다면, 도움이 되지 않을까 합니다! 🙋🏻
From UIWebView To WKWebView
2014년 iOS 8과 함께 WKWebView가 출시되기 전, iOS 개발자들은 UIWebView를 사용했습니다.
UIWebView는 NSURLProtocol을 통해 커스텀 URL Scheme 처리가 가능했습니다.
NSURLProtocol을 서브클래싱하고 등록하면, 커스텀 스킴(예: myapp://)으로 시작하는 모든 요청을 가로채서 처리할 수 있었죠.
// UIWebView 시대의 NSURLProtocol 사용 예시 class CustomURLProtocol: NSURLProtocol { override class func canInit(with request: URLRequest) -> Bool { guard let scheme = request.url?.scheme else { return false } return scheme == "myapp" } override func startLoading() { // 커스텀 리소스 로딩 로직 } } // 등록 URLProtocol.registerClass(CustomURLProtocol.self)
WKWebView 문제점
WKWebView는 다음과 같은 장점들로 UIWebView를 대체하기 위해 등장했습니다.
- WebKit 프레임워크 직접 사용으로 더 빠른 성능
- 향상된 JavaScript 엔진 (Nitro)
- 메모리 효율성 개선
- 더 나은 JavaScript 브릿지 (WKScriptMessageHandler)
하지만 치명적인 단점이 하나 있었죠.
WKWebView는 NSURLProtocol을 지원하지 않았습니다.
이는 로컬 리소스를 로딩하거나, 커스텀 URL Scheme을 처리해야 하는 많은 앱들에게 WKWebView 마이그레이션을 불가능하게 만들었습니다.
특히 하이브리드 앱이나 eBook 리더 같은 앱에서는 이 기능이 필수적이었기 때문에, iOS 8에서 WKWebView가 출시된 후에도 많은 앱들이 UIWebView를 계속 사용할 수밖에 없었습니다.
WKURLSchemeHandler
2017년 iOS 11에서 드디어 WKURLSchemeHandler가 도입되었습니다.
이는 WKWebView에서 커스텀 URL Scheme을 처리할 수 있는 공식적인 방법을 제공하며, NSURLProtocol과 유사한 방식으로 동작합니다.
WKURLSchemeHandler란?
WKURLSchemeHandler는 WebKit이 자체적으로 처리하지 않는 URL Scheme의 리소스를 로딩하기 위한 프로토콜입니다.
Apple 공식 문서에 따르면
A protocol for loading resources with URL schemes that WebKit doesn't handle.
이 프로토콜을 채택한 클래스를 구현하면, WKWebView가 특정 URL Scheme에 대한 요청을 받았을 때 해당 클래스가 리소스 로딩을 직접 처리할 수 있습니다.
특징
WebKit이 처리하지 않는 Scheme만 가능
http:// 나 https:// 같은 표준 스킴은 등록할 수 없습니다.
이는 보안상의 이유로 WebKit이 이미 처리하는 스킴들에 대한 오버라이드를 막기 위함입니다.
비동기 처리
모든 요청은 비동기적으로 처리되며, WKURLSchemeTask를 통해 응답을 전달합니다.
완전한 제어
URL 요청을 받아 원하는 방식으로 리소스를 로드하고, 응답(Response), 데이터(Data)를 단계별로 전달할 수 있습니다.
프로토콜 구조
WKURLSchemeHandler 프로토콜은 두 개의 필수 메서드로 구성됩니다.
protocol WKURLSchemeHandler: NSObjectProtocol { func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) }webView(_:start:)
리소스 로딩을 시작하라는 요청을 받는 메서드입니다.
이 메서드에서 대부분의 작업이 이루어집니다.
- urlSchemeTask.request에서 URLRequest 정보 추출
- 요청에 맞는 리소스 준비 (로컬 파일, 네트워크 요청, 데이터베이스 조회 등)
- URLResponse 생성 및 전달
- 데이터 전달
- 완료 신호
webView(_:stop:)
리소스 로딩을 중지하라는 요청을 받는 메서드입니다.
사용자가 페이지 이동을 취소하거나, WebView가 제거되는 경우 호출됩니다.
여기서는 진행 중인 네트워크 요청을 취소하거나, 필요한 정리 작업을 수행합니다.
다만, stop이 호출된 후에는 urlSchemeTask의 메서드들(didReceive, didFinish 등)을 호출하면 예외가 발생합니다.
WKURLSchemeTask
WKURLSchemeTask는 WebKit이 앱에 커스텀 리소스를 요청하기 위해 사용하는 인터페이스입니다.
이 프로토콜을 통해 요청 정보를 받고, 응답을 전달합니다.
프로퍼티
var request: URLRequest { get }WebView가 요청한 리소스의 URL 정보를 담고 있습니다.
메서드
didReceive(_: URLResponse)
리소스에 대한 응답 정보를 WebKit에 전달합니다.
let response = HTTPURLResponse( url: url, mimeType: "text/html", expectedContentLength: data.count, textEncodingName: "utf-8" ) urlSchemeTask.didReceive(response)didReceive(_: Data)
리소스 데이터를 WebKit에 전달합니다.
여러 번 호출하여 청크 단위로 데이터를 전송할 수 있습니다.
urlSchemeTask.didReceive(data)didFinish()
작업이 성공적으로 완료되었음을 신호합니다.
urlSchemeTask.didFinish()didFailWithError(_: Error)
작업이 실패했음을 알립니다.
urlSchemeTask.didFailWithError(error)
호출 순서
WKURLSchemeTask의 메서드들은 해당 순서로 호출되어야 합니다.
- didReceive(URLResponse) - 한 번
- didReceive(Data) - 0회 이상 (필요한 만큼)
- didFinish() 또는 didFailWithError() - 한 번
이 순서를 지키지 않으면 예외가 발생하거나 WebView가 정상적으로 리소스를 로드하지 못합니다.
Sample
이제 실제로 한번 WKURLSchemeHandler를 구현해보겠습니다 🙋🏻
1. Handler 클래스 구현
import WebKit class CustomSchemeHandler: NSObject, WKURLSchemeHandler { func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { guard let url = urlSchemeTask.request.url else { urlSchemeTask.didFailWithError(NSError( domain: "CustomSchemeHandler", code: -1, userInfo: nil )) return } // 리소스 로딩 로직 guard let data = "Hello World".data(using: .utf8) else { urlSchemeTask.didFailWithError(NSError( domain: "CustomSchemeHandler", code: -2, userInfo: nil )) return } let response = URLResponse( url: url, mimeType: "text/html", expectedContentLength: data.count, textEncodingName: "utf-8" ) urlSchemeTask.didReceive(response) urlSchemeTask.didReceive(data) urlSchemeTask.didFinish() } func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) { // 진행 중인 작업 취소 (필요시) } }2. WKWebView 설정
Handler를 생성했으면, WKWebView에 등록해야 합니다.
let configuration = WKWebViewConfiguration() // Handler 인스턴스 생성 let customHandler = CustomSchemeHandler() // URL Scheme 등록 (반드시 WKWebView 생성 전에 수행) configuration.setURLSchemeHandler(customHandler, forURLScheme: "myapp") // WKWebView 생성 let webView = WKWebView(frame: .zero, configuration: configuration)- setURLSchemeHandler(_:forURLScheme:)는 WKWebView 생성 전에 호출해야 합니다
- WKWebView 생성 후에는 configuration을 변경할 수 없습니다
- 등록한 scheme은 소문자로 변환되어 처리됩니다 (MyApp:// → myapp://)
3. HTML에서 사용
<!DOCTYPE html> <html> <head> <title>Custom Scheme Test</title> </head> <body> <h1>Custom Scheme Handler</h1> <!-- 커스텀 스킴으로 이미지 로드 --> <img src="myapp://images/logo.png" /> <!-- 커스텀 스킴으로 CSS 로드 --> <link rel="stylesheet" href="myapp://styles/main.css"> <!-- 커스텀 스킴으로 JavaScript 로드 --> <script src="myapp://scripts/app.js"></script> </body> </html>
Conclusition
WKURLSchemeHandler는 iOS 11에서 도입된 이후 WKWebView에서 커스텀 URL Scheme을 처리하는 표준 방법이 되었습니다.
하지만 다음 제약사항들을 꼭 기억해야 합니다.
- HTTP/HTTPS 스킴은 등록 불가
- CORS 및 보안 정책 고려 필요
- 메서드 호출 순서 엄수
- 적절한 메모리 관리
WKURLSchemeHandler를 잘 이해하고 활용하면, WKWebView 기반 앱에서 훨씬 더 다양한 기능을 구현할 수 있습니다.
여러분의 프로젝트에서는 WKURLSchemeHandler를 어떻게 활용하고 계신가요? 🤔
References
WKURLSchemeHandler | Apple Developer Documentation
A protocol for loading resources with URL schemes that WebKit doesn’t handle.
developer.apple.com
setURLSchemeHandler(_:forURLScheme:) | Apple Developer Documentation
Registers an object to load resources associated with the specified URL scheme.
developer.apple.com
WKURLSchemeTask | Apple Developer Documentation
An interface that WebKit uses to request custom resources from your app.
developer.apple.com
Custom scheme handling and WKWebview in iOS 11
Apple wanted everyone to migrate from the perfectly fine UIWebview to the new WKWebView when they released it as a part of the iOS 8 SDK.
medium.com
'iOS' 카테고리의 다른 글
Pagination Strategy (1) 2025.11.22 Mach-O 파일 구조 분석해보며 최적화 해보기 (2) 2025.09.13 App Battery Drain (5) 2025.08.09 Diet for iOS App size (feat. App Thinning) (5) 2025.08.02 Meet PaperKit (feat. WWDC 2025) (0) 2025.06.25