iOS/UIKit

WKWebView에서 window.open() 핸들링하기: 완벽 가이드

당근쥬스 2024. 9. 4. 15:47
반응형

iOS 애플리케이션에서 WKWebView를 사용할 때, 자바스크립트의 window.open()을 처리하는 것은 흔하지만 다소 까다로운 작업입니다. window.open()은 일반적으로 새로운 브라우저 창이나 탭을 열려고 하지만, WKWebView에서는 이 동작이 자동으로 이루어지지 않기 때문에 개발자가 직접 핸들링해야 합니다. 이 글에서는 WKWebView에서 window.open()을 효과적으로 처리하는 방법과 navigationAction.targetFramenavigationAction.targetFrame.mainFrame의 동작에 대해 자세히 알아보겠습니다.

 

1. 문제 이해하기

 

웹 페이지에서 window.open()을 사용하면 새로운 브라우저 컨텍스트(탭이나 창)를 만들려고 시도합니다. 그러나 WKWebView에서는 기본적으로 이러한 동작이 지원되지 않기 때문에, 개발자가 이를 수동으로 처리하여 애플리케이션 내에서 원하는 방식으로 콘텐츠가 열리도록 해야 합니다.

 

2. WKWebView 설정하기

 

먼저, WKWebView를 올바르게 설정해야 합니다. 다음은 기본적인 설정 코드입니다:

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // WKWebView 설정
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self

        // 웹뷰를 뷰에 추가하고 레이아웃 설정
        view.addSubview(webView)
        setupWebViewConstraints()

        // 웹 페이지 로드
        if let url = URL(string: "https://example.com") {
            let request = URLRequest(url: url)
            webView.load(request)
        }
    }

    // 웹뷰 레이아웃 설정
    func setupWebViewConstraints() {
        webView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.topAnchor.constraint(equalTo: view.topAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }
}

 

3. window.open() 처리하기

 

window.open()을 핸들링하기 위해서는 WKUIDelegatewebView(_:createWebViewWith:for:windowFeatures:) 메서드를 구현해야 합니다. 이 메서드는 자바스크립트의 window.open()이 호출될 때 트리거되며, 새로운 웹뷰를 생성하거나 현재 웹뷰에서 URL을 로드하는 방식으로 동작을 정의할 수 있습니다.

 

// WKUIDelegate 메서드 구현
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {

    // 새 창이 아닌 현재 웹뷰에서 로드하도록 처리
    if navigationAction.targetFrame == nil {
        webView.load(navigationAction.request)
    }

    return nil  // 새 웹뷰를 생성하지 않음
}

 

4. 새로운 WKWebView 생성 및 모달로 표시 예제

  • 새 창 요청이 있을 때마다 새로운 WKWebView를 생성하고, 이를 모달로 띄워서 사용자가 새 창을 연 것과 같은 경험을 제공할 수 있습니다.
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        // 새로운 WKWebView 생성
        let newWebView = WKWebView(frame: self.view.bounds, configuration: configuration)
        newWebView.uiDelegate = self
        newWebView.navigationDelegate = self

        // 새 웹뷰를 모달로 표시하기 위해 컨트롤러 생성
        let newWebViewController = UIViewController()
        newWebViewController.view.addSubview(newWebView)

        // 새 웹뷰의 레이아웃 설정
        newWebView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            newWebView.leadingAnchor.constraint(equalTo: newWebViewController.view.leadingAnchor),
            newWebView.trailingAnchor.constraint(equalTo: newWebViewController.view.trailingAnchor),
            newWebView.topAnchor.constraint(equalTo: newWebViewController.view.topAnchor),
            newWebView.bottomAnchor.constraint(equalTo: newWebViewController.view.bottomAnchor)
        ])

        // 모달로 표시
        self.present(newWebViewController, animated: true, completion: nil)

        return newWebView  // 새로 생성한 웹뷰를 반환
    }

 

5. navigationAction.targetFrame과 navigationAction.targetFrame.mainFrame 이해하기

 

navigationActiontargetFramemainFrame 속성은 웹 콘텐츠의 네비게이션이 어느 프레임에서 발생하는지를 결정하는 데 중요한 역할을 합니다.

 

  • navigationAction.targetFrame:
    • 이 속성은 네비게이션 액션이 발생할 대상 프레임을 나타냅니다. 예를 들어, 링크 클릭이 새 탭이나 창에서 열리도록 지정된 경우, targetFrame nil이 될 수 있습니다.
    • targetFrame nil인 경우, 보통 target="_blank"와 같은 속성에 의해 새 창이나 탭이 열리도록 요청된 상태를 의미합니다.
  • navigationAction.targetFrame.mainFrame:
    • 이 속성은 네비게이션 액션이 메인 프레임에서 발생하는지 여부를 나타냅니다. 메인 프레임은 웹 페이지의 주 콘텐츠가 로드되는 프레임입니다.
    • mainFrame true라면 네비게이션이 메인 콘텐츠 영역에서 발생한다는 뜻입니다. 반대로, false라면 iFrame과 같은 서브프레임에서 발생한 네비게이션을 의미합니다.

웹에서 각 값이 어떻게 반응하는지:

 

1. 새 창 또는 탭 열기 (target="_blank"):

  • 예: <a href="https://example.com" target="_blank">Open in new tab</a>
  • navigationAction.targetFrame nil이 됩니다. 이는 새로운 창이나 탭을 열려고 한다는 것을 의미합니다.

2. 메인 프레임에서의 네비게이션:

  • 예: <a href="https://example.com" >Open in same tab</a>
  • navigationAction.targetFrame은 메인 프레임을 가리키며, mainFrame 속성은 true입니다. 이는 현재 웹뷰의 메인 콘텐츠가 변경된다는 것을 나타냅니다.

3. 서브프레임에서의 네비게이션 (iFrame 등):

  •  예: <iframe src="https://example.com"></iframe>
  • navigationAction.targetFrame은 서브프레임을 가리키며, mainFrame 속성은 false입니다. 이 경우 네비게이션은 메인 콘텐츠가 아닌 서브프레임에서 발생합니다.
반응형