WKWebView에서 허용한 도메인만 호출하기

시작하며

UIWebView 시절부터 내가 허용한 도메인. 즉, 화이트 리스트 관리를 위해서는 웹이 로딩(loading)되는 시점 혹은 이동(redirection)되는 시점에 허용한 도메인인지 체크를 해왔다. 이 방식은 일반적이긴 하지만 코드가 길어지고 관리하기가 힘든 문제가 있었다.

WKWebView가 강제되기 시작한 시점에서도 메소드명만 바뀌었지 동일한 문제가 있었는데 iOS11부터는 이를 쉽게 적용하고 관리할 수 있게 되었다고 한다.

이는 WKContentRuleListStore를 통하여 Rule List를 정의하면 되는데 이에 대해서 알아보겠다.

ContentRuleList 란?

iOS11 부터 WKContentRuleListStore클래스가 추가되었다. JSON 형태의 규칙을 여기에 저장하고 이를 userContentControlleradd 함으로 쉽게 적용할 수 있다. 결국 규칙을 정의하는 것이 중요하다고 할 수 있다.

이를 위해서는 규칙(Rule List)이 필요하다. 이 리스트는 지정된 형식이 있는데 상세한 내용은 아래 애플 문서에서 볼 수 있다. 하지만 친절하진 않다.. 늘 그렇듯이..

Creating a Content Blocker 문서

Creating a Content Blocker 문서로 이동

중요한 것만 간단히 설명하자면, 이 규칙은 아래와 같은 JSON 형태이다.

trigger는 지정할 도메인 규칙이다.

regex값을 가질 수 있는 url-filter는 필수값이며, regex도 아래 리스트처럼 일부만 사용이 가능한 것 같다. 조금 더 복잡한 regex를 적용해보았는데 허용하지 않는다는 오류가 나타났었다.

url-filter 에 적용할 수 있는 regular expression
url-filter 에 적용할 수 있는 regular expression

url-filter와 함께 아래 첨부한 패턴에 따라 규칙을 더 상세하게 정의할 수 있다.

추가할 수 있는 trigger fileds
추가할 수 있는 trigger fileds

actiontrigger로 지정된 도메인에 대한 규칙이다. 이 규칙은 아래와 같이 차단, 쿠키만 차단, CSS 무시, 이전 규칙 무시, HTTPS로 호출이 있다.

Action Type
Action Type

WKWebView에 규칙 지정하기

지정한 규칙을 웹뷰에 지정하기 위해서는 아래 코드처럼 지정한 규칙을 가져와 WKContentRuleListStore를 통해 컴파일을 하고 최종적으로 웹뷰에 지정하면 쉽게 적용할 수 있다.

let jsonString = "..."
WKContentRuleListStore.default()?.compileContentRuleList(
    forIdentifier: "ContentRuleList",
    encodedContentRuleList: jsonString,
    completionHandler: { ruleList, error in
        guard let ruleList = ruleList else {
            // Error
            return
        }
                
    webView.configuration.userContentController.add(ruleList)
})

WKWebView에서 허용할 도메인 지정하기

위에서 설명한 규칙을 이용하여 원하는 도메인만 허용을 하기 위해서는

regex를 허용한다는 url-filter 값을 이용해보면 되지 않을까란 막연한 생각에 오랜만에 규칙을 만들고 적용을 했더니 허용하지 않는 regex라며 오류가 발생했다… 이 시도에서 위 리스트에서 지정된 regex만 적용이 되는 걸로 이해했다..

어떻게 해결할까 고민을 하다가 ignore-previous-rules라는 것에 눈이 갔고 이 규칙이 앞서 규칙을 무시한다면 기본적으로 다 막아버리고 내가 허용할 도메인에 이 규칙을 적용하면 되지 않을까? 해서 아래와 같은 규칙을 이용하여 테스트를 진행했다.

[
    {
        "trigger": {
            "url-filter": ".*"
        },
        "action": {
            "type": "block"
        }
    },
    {
        "trigger": {
            "url-filter": "file://.*"
        },
        "action": {
            "type": "ignore-previous-rules"
        }
    },
    {
        "trigger": {
            "url-filter": ".*.y8k.me"
        },
        "action": {
            "type": "ignore-previous-rules"
        }
    }
]

테스트 결과 허용하기로 한 도메인에서는 웹 호출이 잘 되었다. 일단 목적은 쉽게 해결을 하였다.

에러 처리하기

허용하지 않는 도메인의 페이지 열기를 시도할 경우 아래 메소드를 통해 오류를 확인할 수 있다.

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { }

error 속성 중 도메인 값은 WebKitErrorDomain이며 코드는 104 이다. 그리고 열려고 시도한 URL은 NSErrorFailingURLStringKey 값으로 알 수 있다.

즉, 허용하지 않은 도메인을 열고자 시도했을 경우 친절하게(?)는 이 값을 이용하여 앱 내에서는 로딩을 허용하지 않았지만 다른 방법으로 (i.e. 사파리로 전달) UX의 흐름을 망치지 않을 수 있다는 것이다.

허용할 도메인 지정 후 오류없이 로딩이 안되는 문제

웹 페이지 중 <iframe> 을 이용하여 화면을 구성한 경우가 있는데 이 때는 어떠한 오류도 없이 로딩이 되지 않았다. 이 때는 위에서 언급한 규칙(Rule list)에 <iframe>을 통해 로딩할 도메인도 명시를 해야한다.

끝으로

이 글로 알아본 규칙은 사파리에서 광고 차단 매커니즘을 웹뷰로 옮겨온 것이라고 한다. 이 정보를 확장하면 광고 차단 앱도 만들어 볼 수 있지 않을까?

11 Shares:
댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

You May Also Like