본문 링크 (Original Link)

웹뷰에서 유동적 글자크기 사용하기

2017.10.27

#

by kharrison, translated by pilgwon

iOS 앱에서 때로는 정적인 HTML 컨텐츠를 보여줄 때 웹뷰가 더 나을 때도 있습니다. 만약 유동적 글자크기를 앱에서 적용했다면 웹뷰의 텍스트가 유저가 선택한 컨텐츠 사이즈를 따르지 않는 것은 매우 어색해 보일 수 있습니다. 다행히도 웹뷰에서 유동적 글자크기를 적용하는 방법이 있습니다.

애플 시스템 폰트 사용하기

HTML 컨텐츠와 함께 유동적 글자크기를 사용하는 것은 쉬운것으로 알려져 있습니다. CSS의 font 속성만 애플 시스템 폰트로 변경하면 됩니다. 만약 애플 기기를 위한 설정이라면 아래와 같이 사용하면 됩니다:

font: -apple-system-body
font: -apple-system-headline
font: -apple-system-subheadline
font: -apple-system-caption1
font: -apple-system-caption2
font: -apple-system-footnote
font: -apple-system-short-body
font: -apple-system-short-headline
font: -apple-system-short-subheadline
font: -apple-system-short-caption1
font: -apple-system-short-footnote
font: -apple-system-tall-body

예를 들어, HTML 바디를 애플 시스템 폰트로 적용한다면 다음과 같을 것입니다:

body {
  font: -apple-system-body;
}

메모: 만약 애플 기기가 아닌 기기에도 서비스한다면 폰트를 불러오지 못 했을 경우의 폰트도 설정해두어야 합니다.

WebKit View를 사용한 예제

WKWebView에서 어떻게 작동하는지에 대한 간단한 예제입니다. 여기 iOS 앱에서 보여줄 간단한 HTML 문서가 있습니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="stylesheet.css" type="text/css" media="all" />
</head>
<body>
<h1>Dynamic Type With WebKit</h1>
<h2>Getting Started</h2>
<p>An example of using dynamic type fonts with HTML content displayed in a WKWebView.</p>
<p>Changing the text size in Settings should also change the text in this web view.</p>
<div class="footnote">For more details see <a href="https://useyourloaf.com/blog/using-dynamic-type-with-web-views/">Using Dynamic Type With Web Views</a></div>
</body>
</html>

이 문서는 CSS 스타일시트인 stylesheet.css 를 참조하고 있고 body, headings 그리고 footnote의 폰트를 설정하는 파일입니다:

body {
    font: -apple-system-body;
}

h1 {
    font: -apple-system-headline;
    color: red;
}

h2 {
    font: -apple-system-subheadline;
    color: blue;
}

.footnote {
    font: -apple-system-footnote;
    color: green;
}

WKWebView 사용하기

HTML을 보여주기 위해서 기본 WKWebView 와 함께 뷰 컨트롤러를 만들 수 있습니다:

import UIKit
import WebKit

class HTMLViewControler: UIViewController {

  private lazy var webview: WKWebView = {
    let preferences = WKPreferences()
    preferences.javaScriptEnabled = false
    let configuration = WKWebViewConfiguration()
    configuration.preferences = preferences
    let webview = WKWebView(frame: .zero, configuration: configuration)
    webview.translatesAutoresizingMaskIntoConstraints = false
    return webview
  }()

정적 HTML 컨텐츠만 보여줄 것이므로 WKWebView 를 만들 때 JavaScript를 비활성화 했습니다. 자동 레이아웃을 사용하여 웹뷰를 슈퍼뷰의 가장자리에 고정합니다:

private func setupViews() {
  view.addSubview(webview)
  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)
      ])
}

아래의 메소드는 어플리케이션 번들에 있는 파일의 HTML을 웹뷰로 로드하는 작업을 처리합니다:

private func loadHTML(_ file: String) {
  if let baseURL = Bundle.main.resourceURL {
    let fileURL = baseURL.appendingPathComponent(file)
    webview.loadFileURL(fileURL, allowingReadAccessTo: fileURL)
  }
}

마지막으로 위에서 세팅한 것들을 전부 viewDidLoad 에서 실행합니다:

override func viewDidLoad() {
  super.viewDidLoad()
  setupViews()
  loadHTML("readme.html")
}

변화에 대응하기

불행하게도 WKWebView 에는 adjustsFontForContentSizeCategory 속성이 없어서 컨텐츠 사이즈가 변경됐을 때 자동으로 폰트를 업데이트할 수 없습니다. 대신에 우리는 노티피케이션을 듣고 뷰를 다시 불러와야 합니다. 아래의 코드를 viewDidLoad 에 추가하고 UIContentSizeCategoryDidChange 노티피케이션을 관찰합니다:

NotificationCenter.default.addObserver(self,
  selector: #selector(contentSizeDidChange(_:)),
  name: NSNotification.Name.UIContentSizeCategoryDidChange,
  object: nil)

타겟 메소드는 웹뷰를 다시 불러옵니다:

@objc private func contentSizeDidChange(_ notification: Notification) {
    webview.reload()
}

아래는 기본 컨텐츠 사이즈를 아이폰 X에 적용했을 때 어떻게 보이는지를 찍은 것입니다:

image1

여기는 접근성 사이즈 중에 가장 큰 컨텐츠 사이즈를 적용했을 때를 찍은 것입니다:

image2

코드

전체 Xcode 프로젝트를 아래의 GitHub 래포지토리에서 얻을 수 있습니다:

더 읽을거리