WebView 구성의 IOS App 속도 개선 작업

서론

WebView로 구성된 IOS App의 처음 진입 및 페이지 이동간 속도 개선 작업을 진행하게 되었다. Native App 이라면 이런 저런 속도 개선 작업을 코드 단위에서 진행할 수 있겠지만, WebView로 구성된 IOS App의 경우 사실상 할 수 있는게 별로 없다. Web Source의 무거운 외부 종속 라이브러리 등을 첨삭하여 개선하는 방법이 가장 빠른 길이지만 그럼에도 불구하고 App에서도 개선할 수 있는 작업이 있을까 고민하게 되었다.

 

현재 앱 구성 파악

현재 본인의 앱 상태가 어떤지 파악해야 하는데, 나의 경우 App을 실행할 때 LaunchScreen 표시 이후 WebView 로딩까지 매끄럽지 않고 특히 Custom Loading Indicate (개발자가 임의로 만들어낸 로딩 지연 표현)가 무거워서 앱 자체가 너무 느려보이는 현상이 있었다.

때문에 LaunchScreen to WebView Loading 사이의 여백 기간을 못 느끼게 수정하고, Loading을 인식시켜서 체감 시간을 길게 만드는 Custom Loading Indicate를 제거하고 대신에 UIProgressView로 로딩을 인지시켜주는 용도로만 사용하여 체감 시간을 대폭 감소시키는 작업을 진행했다.

WKWebView

기존의 AppDelegate에서의 LuanchScreen 표출이 너무 짧아 넣어준 것 같은 sleep 코드들은 과감히 제거하고, Custom Loading Indicate bar에 관련된 로직도 전부 날렸다.

WebView 특성상 스토리보드가 많이 존재할 필요가 없다고 생각하여 LaunchScreen View Controller와 똑같은 CustomLaunchScreenViewController (이하CustomLaunchScreenVC)를 생성하여 Main StroyBoard에 추가하였고 UIViewController의 override된 기본 function들을 파악하여 WebView가 전부 로딩되기 전 까지 CustomLaunchScreenVC를 표출하고, webView로딩 이후 dismiss시키는 로직을 추가하였다.

내 머리속에서는 정상적으로 작동을 해야하는데 작동을 안해서 이유를 찾아보니, viewDidLoad()에서 CustomLaunchScreenVC의 modalPresentation을 시도하는 경우, Main View Controller가 아직 화면에 나타나지 않은 상태에서 실행되기 때문에 정상 적용이 안되는 것 처럼 보일때가 있다고 한다. 때문에 viewDidAppear() 내에서 관련 코드를 적용시켰다.

LaunchScreen 관련 예제

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    showLaunchScreen()
}

private func showLaunchScreen()
{
    print("Test :: Show Launch Screen")
    // storyboard에서 "LaunchScreenClone" Identifier를 가진 ViewController를 가져옵니다.
    launchScreenVC = storyboard?.instantiateViewController(withIdentifier: "CustomLaunchScreenVCID")
    
    // launchScreenVC를 modal로 표시합니다.
    if let vc = launchScreenVC {
        vc.modalPresentationStyle = .overFullScreen
        present(vc, animated: false)
    }
}

private func hideLaunchScreen()
{
    print("Test :: Hide Launch Screen")
    
    UIView.animate(withDuration: 0.3, animations: {
        self.launchScreenVC?.view.alpha = 0
    }, completion: { _ in
        self.launchScreenVC?.dismiss(animated: false, completion: nil)
    })
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    hideLaunchScreen()
}

ProgressBar 관련 예제

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 프로그레스바 추가
    progressBar = UIProgressView(progressViewStyle: .default)
    progressBar.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(progressBar)

    // 프로그레스 바 색 빨간색으로 설정
    progressBar.progressTintColor = UIColor.red
    // 프로그레스 바 두께 설정 2pt
    progressBar.heightAnchor.constraint(equalToConstant: 2).isActive = true
    
    // 상단에 프로그레스 바 위치 설정
    NSLayoutConstraint.activate([
        progressBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        progressBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        progressBar.trailingAnchor.constraint(equalTo: view.trailingAnchor)
    ])
    
    webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)

}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "estimatedProgress" {
        UIView.animate(withDuration: 0.3) { [weak self] in
            self?.progressBar.setProgress(Float(self?.webView.estimatedProgress ?? 0), animated: true)
        }
    }
}


deinit {
    webView.removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress))
}

// 숨기고 싶을 때 호출하세용
func hideProgressBar()
{
    progressBar.isHidden = true
    progressBar.progress = 0.0
}

    

'Language > Swift' 카테고리의 다른 글

IOS WKWebView Pull Down To Reload 구현하기  (0) 2023.11.30