CLOSE SEARCH

Text Kit : focus on Legibility and easy API #2

Text Kit : focus on Legibility and easy API #1에서 이어지는 글입니다.

ios7_textoption2

ios7_textoption1


Dynamic Type

iOS 7 설정앱에는 텍스트 가독성을 위한 새로운 메뉴가 추가되었습니다. Text Scaling이라는 기술을 통해 “일반 > 텍스트 크기” 설정에서 시스템 전역적으로 폰트의 크기를 설정할 수 있으며, Text Style이 적용된 텍스트들은 설정된 크기에 따라 동적으로 변경됩니다. Text Style은 용도에 따라 미리 정의되어 있는 텍스트 스타일로 Dynamic Type을 위한 필수 요소입니다. iOS 7에 내장된 기본앱들은 Dynamic Type을 충실히 구현하고 있습니다. 아래의 그림을 통해 사용자가 설정한 텍스트의 크기에 따라 메모앱의 본문 텍스트 크기가 변경되는 것을 확인할 수 있습니다.

[one_third]textscaling_memo1[/one_third]

[one_third]textscaling_memo2[/one_third]

[one_third_last]textscaling_memo3[/one_third_last]

모바일 디바이스에서 가독성에 영향을 주는 요소는 다음과 같다고 볼 수 있습니다.

  • 화면 해상도와 밝기
  • 폰트의 종류
  • 폰트의 크기
  • 자간
  • 줄의 높이
  • 폰트 주변의 여백

레티나 디스플레이를 통해 첫번째 요소에 대한 개선을 이루었다면, Dynamic Type은 나머지 요소들을 상황에 맞게 조절하는 방식으로 가독성을 향상시키고 있습니다.

dynamic_type

일반적으로 작은 크기의 폰트는 굵기가 굵을수록 가독성이 높고, 큰 폰트는 가늘수록 가독성이 높다고 합니다. Apple은 이런 내용을 기초로 Text Style을 통해 생성된 폰트들의 크기가 작아질수록 폰트를 두껍게 하고, 커질수록 폰트가 얇아지게 하는 방식을 적용하고 있습니다. 뿐만 아니라, 정교한 알고리즘을 통해 각 크기에 최적화된 자간, 줄높이 등을 적용한 폰트로 텍스트를 보여주기 때문에 이전에 비해 더 뛰어난 가독성을 제공할 수 있게 된 것입니다.

이처럼 가독성과 관련된 상세한 구현은 시스템에서 모두 처리해주기 때문에 개발자는 미리 정의된 Text Style을 사용해서 폰트를 얻어온 후, 원하는 곳에 적용하기만 하면 됩니다.

 

Font for Dynamic Type

iOS 6까지는 주로 폰트의 이름이나 크기를 통해서 사용할 폰트를 생성했었습니다. 이렇게 생성된 폰트에는 Text Scaling이 적용되지 않기 때문에, 사용자가 설정한 텍스트 크기에 관계없이 항상 동일한 크기를 유지합니다. 이전과 같이 고정된 크기의 폰트를 생성하는 방식은 설계상의 필요에 의해서 크기가 항상 고정적이어야 하는 부분에서만 최소한으로 사용하도록 하고, 나머지 부분에서는 항상 Dynamic Type 기술을 적용하는 것이 좋습니다. 앞으로 다양한 화면 해상도와 텍스트 크기의 동적 변화에 유연하게 대응하기 위해서는 Dynamic Type과 더불어 Auto Layout도 적절히 사용할 수 있어야 합니다.

Regular Styles

1번 라인은 크기를 사용해서 시스템 폰트를 얻어오는 코드이고, 2번 라인은 iOS 7에서 새롭게 제공되는 Text Style을 통해 폰트를 얻어오는 코트입니다. 앞으로는 2번 라인과 같이 미리 정의된 스타일을 사용해서 앱에서 Dynamic Type의 이점을 충분히 활용하도록 해야 합니다. 사용 가능한 스타일들은 다음과 같은 문자열 상수를 통해 제공됩니다.

Variant Styles

그리고 각 스타일은 Bold, Italic 과 같은 다양한 변형 스타일도 제공합니다. preferredFontForTextStyle: 메소드는 가장 기본적인 Regular 스타일을 리턴하기 때문에, 아래와 같은 변형 스타일 폰트를 얻기 위해서는 UIFontDescriptor 클래스를 통해 원하는 변형 스타일을 추가로 지정해 주어야 합니다.

위의 두가지 코드 예제는 각각 본문 스타일 폰트(UIFontTextStyleBody)의 Bold 스타일과 Italic 스타일 폰트를 얻어오는 방법을 보여줍니다. 마지막 라인의 size: 파라미터에 0.0을 보내는 것은 스타일이 가지고 있는 기본 크기를 그대로 사용하겠다는 의미이며, 다른 값을 전달하면 기본 크기를 무시하고 지정한 크기의 폰트를 리턴하며 Text Scaling 또한 무시됩니다.

Font Matching

iOS 7에서 새롭게 제공되는 UIFontDescriptor 클래스는 코어 텍스트에서 사용하던 CTFontDescriptor와 마찬가지로 폰트에 대한 속성을 서술하는 역할을 합니다. 텍스트 킷은 Font Descriptor에 서술된 속성에 가장 일치하는 폰트를 매칭시키는 두가지 방법을 제공합니다. 바로 앞에서 살펴본 두가지 예제에서 사용된 방식을 Implicit matching이라고 하며, 항상 지정된 속성에 가장 가까운 폰트를 리턴해줍니다.

이에 반해, Explicit matching은 Font Descriptor에 설정되어 있는 폰트 속성과 일치하는 폰트의 목록을 매칭시켜줍니다. 이 방식은 Implicit matching에 비해 좀 더 엄격한 매칭 조건을 사용하기 때문에 사용 가능한 폰트를 찾을 수 없는 경우가 있으므로, 이에 대한 예외 처리를 적절히 해 주어야 합니다.

위의 예제코드는 Arial 폰트 패밀리에 대한 Font Descriptor를 생성하고, matchingFontDescriptorsWithMandatoryKeys: 메소드를 사용해서 UIFontDescriptorFamilyAttribute 속성이 일치하는 모든 폰트의 Font Descriptor 목록을 가져옵니다. 속성이 포함된 NSSet 객체 대신 nil을 파라미터로 전달하는 경우에는 모든 폰트 속성을 사용하여 매칭시킵니다.

Font Descriptor Archiving

Font Descriptor의 장점 중 하나는 속성을 아카이브 한 후에 재사용할 수 있다는 것입니다. UIFontDescriptor 클래스는 기본적으로 아카이브를 지원하지만, 직접 fontAttributes 메소드가 리턴하는 NSDictionary 형태의 속성을 아카이브 해 두었다가 fontDescriptorWithFontAttributes: 또는 initWithFontAttributes: 메소드를 통해 동일한 속성으로 복원하거나, fontDescriptorByAddingAttributes: 메소드를 통해 이미 존재하는 Font Descriptor에 아카이브된 속성을 추가할 수도 있습니다.

 

Font Features

모든 폰트는 자신만의 독특한 특성을 가지고 있고, 텍스트 킷은 Font Descriptor를 통해 이러한 특성을 수정할 수 있도록 해줍니다. 예를 들어, Helvetica Neue 폰트는 숫자 사이의 공백 너비를 지정할 수 있는 “Number Spacing” 특성과 특수 문자를 대체 문자로 변경할 수 있는 “Character Alternatives” 특성을 가지고 있고, Times New Roman 폰트는 합자(Ligature)를 처리하는 방식을 지정할 수 있는 “Ligatures” 특성을 가지고 있습니다. 이렇게 각 폰트마다 가지고 있는 특성이 서로 다르기 때문에, 특성을 변경하고자 하는 경우에는 해당 폰트가 가지고 있는 특성을 파악해야 합니다.

폰트의 특성을 확인하기 위해서는 CFFont 에서 제공하는 CTFontCopyFeatures 함수를 사용해야 합니다.

이 함수는 폰트의 특성이 담긴 배열을 리턴하는데, 만약 폰트가 특성을 가지고 있지 않은경우 NULL이 리턴됩니다. 위의 코드를 통해 Helvetica Neue의 특성을 로그로 출력해보면 다음과 같이 지정가능한 특성의 목록이 출력됩니다.

font_features_helvetica_neue

여기에서 주목해야 할 키는 CTFeatureTypeIdentifier와 CTFeatureSelectorIdentifier 입니다. 이 두개의 키가 가지고 있는 값은 Font Descriptor를 통해 특성을 변경할 때 사용됩니다.

다음 코드는 Helvetica Neue 폰트의 Number Spacing 특성을 Proportional Numbers로 변경합니다. features 배열에 있는 딕셔너리에서 사용된 각 키의 값을 주의깊에 보면, Number Spacing 특성을 나타내는 6과 Proportional Numbers를 나타내는 1이 각각 사용된 것을 알 수 있습니다.

numberspacing_result

Proportional Numbers로 설정된 경우에는 위쪽 숫자와 같이 숫자 사이의 공백이 너비에 비례하여 출력됩니다. 아래쪽에 있는 No Change를 사용한 경우와 비교해보면 어떤 차이가 있는지 쉽게 이해하실수 있을것입니다.

 

BYOF(Bring your own fonts)

시스템이 제공하는 폰트가 아닌 커스텀폰트를 사용하고자 한다면 앱 내부에 폰트를 설치해야 합니다. iOS 6와 마찬가지로 코어 텍스트의 폰트 메니저를 사용해서 구현할 수 있습니다.

커스텀 폰트를 설치하는 가장 쉬운 방법은 폰트 파일을 번들로 복사하고 Info.plist 파일에 UIAppFonts(Fonts provided by application) 키를 추가한 다음, 폰트의 이름을 입력해 주는 것입니다.  이렇게 설치된 폰트는 시스템 폰트를 사용하는 방법과 동일하게 사용할 수 있습니다.

하지만 사용자가 앱을 설치한 후 직접 원하는 폰트를 다운로드하도록 구현한 경우에는 앞에서 설명한 방법을 사용할 수 없기 때문에, 코드를 통해 폰트를 추가해주야 합니다. CTFontManager는 다음과 같이 폰트를 등록할 수 있는 함수를 제공합니다.

이 함수를 통해 등록된 폰트는 앞서 설명한 방식과 마찬가지로 시스템 폰트와 사용법이 동일하며, Registered Font라고 부릅니다.

반면 위의 두 함수는 폰트 디스크립터를 통해 폰트를 참조할 수 있는 방법을 제공합니다. 이렇게 참조된 폰트는 Unregistered Font라고 하며, 시스템 폰트나 Registered Font와 달리 이름을 통해 참조할 수는 없습니다. 하지만 리턴된 값을 UIFontDescriptor로 바로 변환할 수 있기 때문에 폰트 디스크립터를 통해 폰트를 생성하는 경우에 유용하게 사용할 수 있습니다.

 

Simple Rules

이 글에서 폰트와 관련된 여러가지 기술에 대해 설명했지만, iOS 7에서 텍스트 킷을 통해 폰트를 사용할 때는 두가지 간단한 규칙만을 기억하면 됩니다.

[list style=”check”]

  • Text Style을 통해 폰트를 얻어온다. Bold나 Italic과 같은 스타일이 필요한 경우에는 Font Descriptor를 사용해서 변형 스타일을 지정해준다.
  • 폰트의 이름이나 고정된 크기를 통해 폰트를 얻어오는 방식은 반드시 첫번째 방식으로 원하는 기능을 구현할 수 없는 경우에만 사용한다.

[/list]

Filed under: Apple WWDC 2013, iOS