Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

teunteun2

JavaScript 웹뷰 -> iOS WKWebView 통신 본문

iOS

JavaScript 웹뷰 -> iOS WKWebView 통신

teunteun2 2024. 5. 5. 16:09

우선 앱에서 웹뷰를 띄워야하면 SFSafariViewController 혹은 WKWebView를 사용한다

웹앱 통신에 대해 알아보기 전에 간단히 왜 웹인터페이스와의 상호작용을 구현할 땐 WKWebView를 사용하는지 부터 , ..

SFSafariViewController

SFSafariViewController 는 띄우고자 하는 웹 url을 사파리 뷰로 띄우는 것이기 때문에,

웹뷰 커스텀이 필요없거나 , 웹 컨텐츠와의 상호작용 없이 그저 웹뷰를 띄우기만 할 때 자주 쓰인다.

 

그리고 사파리 인터페이스를 앱에서 그대로 띄우는 것이라서 유저가 사파리 기능을 사용할 수 있다.

하지만 유저가 SFSafariViewController를 통해 어떤 사파리 기능 (자동완성 데이터, 검색 기록, 웹사이트 데이터)을 사용했는지는 알 수 없다 (접근 못함)

 

웹 인터페이스를 제어하고 싶거나, 웹과 상호작용을 하고 싶다면 WKWebView 를 사용하라고

SFSafariViewController 공식문서에 기재되어 있다.

https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller

 

SFSafariViewController | Apple Developer Documentation

An object that provides a visible standard interface for browsing the web.

developer.apple.com

 

WKWebView

아 사파리뷰다 ! 라고 바로 인식할 수 있는 SFSafariViewController에 반해

앱 UI와 별 차이를 못느끼게끔 웹뷰를 띄울 수 있는 WKWebView

 

웹뷰가 앱 레이아웃을 더 잘 충족시킬 수 있을 때 사용한다 (ㅋㅋ)

(혹은 앱 업데이트 없이 웹뷰 콘텐츠만 바꿔 자주 업데이트를 하고싶을 때)

 

delegate 객체를 통해 navigation이나 사용자 경험을 제어할 수 있다

(ex1. 사용자가 웹 콘텐츠에서 링크를 클릭했을 때 navigation delegate를 통해 특정 조건 불충족 시 네비게이션 못하도록 막을 수 있음)

(ex2. UI delegate를 사용해서 웹과의 상호작용데 대한 응답으로 UI 요소를 표시할 수 있음)

https://developer.apple.com/documentation/webkit/wkwebview

 

WKWebView | Apple Developer Documentation

An object that displays interactive web content, such as for an in-app browser.

developer.apple.com


 

웹(JavaScript로 구현된) -> 앱(iOS)

웹에서 발생된 메세지를 앱에서 받는 기능을 구현해야 했다.

그냥 이렇게 저렇게 하면 된다고 쓰려다가 WKUserContentController랑 WKScriptMessageHandler가 무엇인지 위주로 정리해보았다.

 

 

WKScriptMessageHandler

웹페이지의 JavaScript 코드로부터 메세지를 받을 수 있는 인터페이스

https://developer.apple.com/documentation/webkit/wkscriptmessagehandler

 

WKScriptMessageHandler | Apple Developer Documentation

An interface for receiving messages from JavaScript code running in a webpage.

developer.apple.com

 

자바스크립트로 구현된 웹뷰로부터 메세지를 받아야할 때 WKScriptMessageHandler 프로토콜을 채택한다

 

1. JavaScript 코드에서 앱(iOS)에서 설정한 <messageHandlerName> (ex. dismiss) 을 대상으로 하는 메세지를 보낸다

window.webkit.messageHandlers.<messageHandlerName>.postMessage(<messageBody>)

 

 

2. WebKit이 WKScriptMessageHandler 프로토콜의 userContentController(_: didReceive:) 메서드를 호출한다

3. userContentController(_: didReceive:) 내부에서 받은 메세지를 핸들링한다

extension WKWebViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "dismiss" {
            // 핸들링
        }
    }
}

어떤 메세지를 받았는지 <messageHandlerName>, 그리고 해당 핸들러가 어떤 바디를 가지고 왔는지 <messageBody> 를 확인하려면 각각 message.name , message.body 에 접근

 

 

 

 

근데 생각해보면 메세지핸들러 이름을 앱과 프론트 두군데에서 '이 이벤트의 이름은 <messageHandlerName> 이라고 하자!' 라고 해준 적이 없다. 위 내용만 읽어보면 일방적으로 프론트에서 <messageHandlerName> 라는 이름으로 메세지를 보내고 있을 뿐 ,..

 

WKUserContentContrller를 통해 메세지 핸들러 이름을 만들어주어야 한다

 

 

 

WKUserContentController

JavaScript 코드와 웹 간의 상호작용을 관리하고 웹뷰의 내용을 필터링하기 위한 객체

 

-> WKUserContentController 객체는 웹뷰에서 실행되는 자바스크립트 코드와 앱(iOS) 사이의 'bridge'를 제공하며 다음과 같은 작업을 수행한다

  • 웹뷰의 웹페이지에 자바스크립트 코드를 주입한다
  • 앱의 네이티브 코드로 호출할 수 있는 커스텀 자바스크립트 함수를 만든다 (install... 이라고 되어있는데 만든다고 기재)
  • 웹페이지가 제한된 컨텐츠를 불러오지 못하도록 필터링 한다

WKUserContentConroller은

WKWebView의 configuration인 WKWebViewConfiguration 객체 userContentController 속성에 할당하는 객체이다

let contentController = WKUserContentController()
contentController.add(self, name: "dismiss")
// javascript쪽에서 보내주어야 하는 메세지 핸들러 이름을 add 해준다

let configuration = WKWebViewConfiguration()
configuration.userContentController = contentController
// WKUserContentController은 WKWebViewConfiguration의 userContentController 속성

webView = WKWebView(frame: view.frame, configuration: configuration)