본문 링크 (Original Link) 일본어 번역 링크 (Original Link)

iOS에서 텍스트 스타일링하기: 커닝(Kerning) 포인트

by Rob Huebner
translated Korean by pilgwon
translated Japanese by asuka0130

image1

달리 주목할만한 것이 없는 수요일 아침에, Slack의 알림 소리가 조용한 침묵을 깼습니다. 그건 디자인쪽 이었습니다. 그들은 우리의 폰트에 약간의 수정이 가능하냐고 물었습니다. “오 네, 그리고 우리는 모든 트래킹(tracking)들도 약간 조정해야 합니다.”

오우. 😳

기본적인 속성

이 요청이 왜 큰 요청인지 이해하기 위해, iOS에서 텍스트를 보여주는데에 가장 기본적인 방법인 UILabel을 사용해봅시다.

만약 당신이 작업하는데 UIKit을 사용한다면, UILabel에 대해 아주 잘 알고 있을 것입니다. 이것은 몇 가지의 겉모습을 커스터마이즈 가능한 속성인 font, textColor 그리고 textAlignment를 가지고 있습니다. 하지만, 그 후엔, 당신은 벽에 부딪히기 시작합니다. 어떤 멋있는 작업을 하려고 하면 보통 텍스트와 그에 맞는 적절한 속성을 가진 NSAttributedString을 필요로 하고, label의 attributedText 속성을 사용합니다.

그것은 보기에 충분히 괜찮아 보이지만, 이 접근법을 확장하거나 거친 면을 발견하려고 한다면:

  1. attributedString을 만드는 것은 꽤나 투박하고 불필요해 보입니다.
  2. label의 텍스트가 유동적이라면, 스타일이 바뀌지 않는다고 해도 당신은 모든 attributedString을 텍스트를 바꾸려고 할 때마다 새롭게 만들어야합니다.
  3. 문자열의 스타일을 표준화하거나, 디폴트값을 기반으로 구축하는 좋은 방법은 존재하지 않습니다.

트래킹 또는 커닝(애플이 이것을 부르는 방식)은 attributedString에서만 쓸 수 있는 파라미터의 하나 입니다. 그래서, 만약 우리가 폰트의 커닝을 전체적으로 조정하려면, 우리는 text대신에 attributedText를 전체적으로 써야합니다. 불행하게도, 이것이 어떻게 앱 전체적인 폰트 공백 조정을 해달라는 무고한 요청이 코드 복잡도를 급증시킬 수 있는지를 보여줍니다.

image2

이제 더 나은 폰트 시스템을 만들어 봅시다.

텍스트 스타일들

저희는 attributed string을 필요한 모든 곳에 수동으로 추가하는 작업은 정말 하기 싫었습니다. 우리의 정적 텍스트 스타일은 텍스트 자체와는 독립적으로 선언하는 것이 이상적입니다. 그렇게 하면, 우리는 label의 라이프 사이클의 초반에 스타일을 설정할 수 있고, 다시는 그것에 대해 생각하지 않아도 됩니다.

이를 위해, 우리는 iOS를 위한 선언적 텍스트 스타일링 라이브러리인 StyledText를 작성했습니다. StyledText는 두 가지 새로운 컨셉을 설명합니다: TextStyle, 특정 텍스트 스타일 파라미터 세트를 나타내는 타입; 그리고 스타일을 받아들이고 텍스트 내용을 그리는데 사용하는 UIView의 서브 클래스인 Styled. 이 개선점들은 우리가 원하는 패턴을 따라갈 수 있었습니다. 그냥 TextSTyle을 위에 만들고, StyledLabel로 보내면 됩니다:

class ViewController: UIViewController {
    private let styledLabel: StyledLabel = {
        let label = StyledLabel(frame: .zero)
        label.textStyle = TextStyle(font: .systemFont(ofSize: 14),
                                   color: .blue,
                             lineSpacing: 4.0,
                                    kern: 1.5)
        return label
    }()

    func updateLabel() {
        styledLabel.text = "This is a simple string"
    }
}

실용적인 기본값들

앞에서 나온 것들이 아주 훌륭하지만, 여전히 우리는 궁극적인 딜레마를 해결하지 못했습니다. 어떻게 우리는 앱의 커닝을 조정할 수 있을까요? 그에 대한 답은 TextStyle에 놓여있습니다. 이번 시간에는 TextStyleDefaultsGenerator라고 부를 것입니다. 우리가 이 중 하나를 설정하면, 스타일이 지정되지 않은 채로 초기화 될 때마다 커닝의 기본값을 묻습니다.

extension TextStyle: TextStyleDefaultsGenerator {
    private static let defaultCeraKern: CGFloat = -0.2
    private static let defaultChronicleKern: CGFloat = -0.2
    static public func defaultKern(for font: UIFont) -> CGFloat? {
        if font.fontName.contains("Cera") {
            return defaultCeraKern
        } else if font.fontName.contains("Chronicle") {
            return defaultChronicleKern
        }
        return nil
    }
}

문제 해결. 😎

Blue Apron iOS 앱에 TextStyle을 적용하고 나서, 우리는 폰트를 어디서든지 상세사항까지 변경할 수 있고 오버헤드에 부담도 적게 줄 수 있었습니다. 그리고 우리는 StyledText를 오픈 소스 라이브러리로 iOS 커뮤니티에 공개할 수 있어서 너무 기쁩니다. 우리는 그것을 계속해서 만들어서 모바일 플랫폼을 위한 강력한 타이포그래피 도구가 될 것을 희망합니다.

보너스: 자유로운 접근성이 승리합니다

이제 우리는 모든 텍스트 스타일링을 중앙집중식으로 만들었고, 우리가 할 수 있는 쿨한 것들이 아주 많습니다. 예를 들어, 우리는 유저가 그들의 시스템 폰트 사이즈를 변경할 수 있는 애플의 도구인 유동적 글자 크기에 대한 지원할 수 있습니다. 그래서 우리는 했습니다! StyledText의 모든 상자에 무료로 포함되는 것은 모든 TextStyle에 유동적 글자 크기를 지정할 수있는 기능입니다. 사이즈를 골람보세요, 어떤 사이즈든요:

image3

당신의 텍스트를 꾸미세요

GitHub에 있는 우리의 README로 시작하세요! 오늘 확인하시고 우리에게 당신이 어떻게 생각하는지 알려주세요. 컨트리뷰트나 응원은 환영입니다!

[ * ] 타이포그래피는 실제로 “커닝(kerning)”을 두 글자 사이의 공간으로 정의합니다. 예를 들어, ‘A’와 ‘V’의 모양은 겹쳐질 수 있기 때문에 많은 폰트에서 가까이 붙여집니다. “트래킹(Tracking)”은 더 큰 임의의 문자 집합에 대해 문자 간격이 어떻게 조정되는지를 나타냅니다. 하지만 애플은 오직 문자열 속성인 NSKernAttributeName으로 앞의 두 개념을 모두 제공하므로, StyledText도 마찬가지 입니다.