우리가 앱과 모바일 서비스를 만들고 제공하는 이유는 많은 사람에게 도움이 되기 위해서입니다.
이를 위해 구형 스마트폰, 낮은 iOS 버전에서도 앱과 기능이 정상적으로 동작하도록 로직을 파편화하거나, 심지어 생산성이 높은 개발 도구를 포기하기도 합니다.
그러나 가끔, 우리는 세계 인구의 15%에 해당하는 엄청난 규모의 사람들이 필요로 하는 기능을 신경 쓰지 않고 개발하는 경우가 있습니다.
전 세계 인구의 15%는 장애를 가지고 있습니다.
이 사람들은 우리의 제품을 사용하고 싶지만, 영구적이거나 일시적, 또는 환경적인 문제로 인해 일반적인 방법으로 앱을 사용하는 데 어려움을 겪고 있습니다.
이들이 앱을 쉽게 이용할 수 있도록 하기 위해 우리는 "접근성"을 보장해야 합니다.
이번 글부터는 UIKit 또는 SwiftUI에서 접근성을 지원하는 방법에 대해 소개할 예정입니다.
오늘은 그 중에서도 글자의 크기를 변경하는 Dynamic Type에 대해 알아보겠습니다.
Dynamic Type은 사용자가 설정한 텍스트 크기에 따라 앱의 텍스트 크기가 자동으로 조정되는 접근성 기능입니다.
이 기능을 활용하기 위해서는 설정 > 손쉬운 사용 > 디스플레이 및 텍스트 크기 > 더 큰 텍스트 로 이동하여야 합니다.
SwiftUI의 Text는 기본적으로 Dynamic Type이 적용되어 있습니다.
하지만 UIKit의 경우, 개발 당시 접근성에 대한 설계를 하지 않았어서 이 값을 수동으로 적용해주어야 합니다.
따라서 UIKit의 경우 UIFont.preferredFont(fotTextStyle:)
구문과 adjustsFontForContentSizeCategory
를 설정해 주어야 합니다.
앱 개발을 하다 보면 앱에 맞는 특정 폰트를 사용할 때가 있습니다.
이런 경우에는 UIFont.preferredFont(forTextStyle:)
구문을 활용해 Dynamic Type을 적용할 수 있습니다.
/// SwiftUI의 경우
extension View {
func customFont(named fontName: String, size: UIFont.TextStyle) -> some View {
self.font(.custom(fontName, size: UIFont.preferredFont(forTextStyle: size).pointSize))
}
}
/// UIKit의 경우
label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: UIFont(name: "NanumGothicLight", size: UIFont.preferredFont(forTextStyle: .body).pointSize)!)
label.adjustsFontForContentSizeCategory = true
TextStyle | 기본 크기 |
---|---|
.caption2 | 11 |
.caption1 | 12 |
.footnote | 13 |
.subheadline | 15 |
.callout | 16 |
.body | 17 |
.headline | 17 |
.title3 | 20 |
.title2 | 22 |
.title1 | 28 |
.largeTitle | 34 |
Dynamic Type의 경우 텍스트의 크기가 커지기 때문에 Layout이 망가질 가능성이 높습니다.
이 때문에 Dynamic Type의 크기를 제한하는 방법도 있습니다.
iOS15 이상의 SwiftUI에서는 .dynamicTypeSize(_:)
를 이용해 크기를 제한하면 됩니다.
UIKit에서는 traitCollectionDidChange(_:)
에서 수동으로 처리할 수 있습니다.
/// 아래로 갈 수록 크기가 큼
xSmall
small
medium
large
xLarge
xxLarge
xxxLarge
accessibility1
accessibility2
accessibility3
accessibility4
accessibility5
struct ContentView: View {
var body: some View {
Text("Dynamic Type Test")
Text("SwiftUI의 Text입니다.")
.dynamicTypeSize(.xSmall ... .xxxLarge)
LimitedDynamicTypeLabelRepresentable()
.frame(height:50)
Spacer()
}
}
struct LimitedDynamicTypeLabelRepresentable: UIViewRepresentable {
func makeUIView(context: Context) -> some UIView {
let label = LimitedDynamicTypeLabel()
label.text = "UIKit의 Label입니다."
return label
}
func updateUIView(_ uiView: UIViewType, context: Context) { }
}
final class LimitedDynamicTypeLabel: UILabel {
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let maximumCategory = UITraitCollection(preferredContentSizeCategory: .extraExtraExtraLarge)
let currentCategory = self.traitCollection.preferredContentSizeCategory
if currentCategory > maximumCategory.preferredContentSizeCategory {
self.adjustsFontForContentSizeCategory = false
self.font = UIFont.preferredFont(forTextStyle: .body, compatibleWith: maximumCategory)
} else {
self.adjustsFontForContentSizeCategory = true
self.font = UIFont.preferredFont(forTextStyle: .body)
}
}
}
앱의 접근성은 단순히 기능을 넘어, 더 많은 사용자들이 제품을 원활하게 이용할 수 있도록 돕는 중요한 요소입니다. Dynamic Type을 활용하여 텍스트 크기를 자동으로 조정하면, 사용자가 원하는 크기로 쉽게 텍스트를 조정할 수 있어, 시각적 어려움을 겪는 사용자에게 큰 도움이 됩니다.
UIKit과 SwiftUI에서 Dynamic Type을 구현하는 방법을 익히고, 사용자 맞춤형 폰트를 적용하는 방법을 통해, 우리는 더 많은 사람들에게 도움이 되는 제품을 제공할 수 있습니다.
모든 사용자가 차별 없이 앱을 사용할 수 있도록, 접근성을 고려한 개발은 선택이 아닌 필수임을 잊지 말아야 합니다.
역시 접근성의 왕이시네요 ..굉장히 단순한 코드로 제공을 할 수 있단 게 놀랍네요!!!!!
잘 보고 갑니다 :)