
👇 최근 퍼블리싱한 패키지 하나를 소개드리려고 합니다.
Pub.dev에서 Xtyle 보기
서비스 중인 앱 프로젝트에 디자인 시스템을 도입하면서 폰트가 변경됐습니다.
디자이너분 께서 다음과 같은 요구사항을 말씀해주셨어요.
🙋♀️ 개발자님!
디자인 적용할 때 영어/숫자는 Lato 폰트로,
한글은 NotoSans 폰트로 적용해주세요!
Flutter는 RichText 위젯을 통해 스타일이 다른 텍스트를 그릴 수 있습니다. 하지만, 실제 프로덕트에서는 문제가 단순하지 않죠... :)
서버에서 날아오는 동적인 문자열 데이터는 어떻게 적용해줄까라는 고민에 빠졌습니다.
우선 해당 요구사항을 검토해본 뒤, 말씀드리겠다고 하고
패키지 없이 플러터의 기본 기능으로 구현할 수 있는가?
No!
해당 문제를 해결해주는 패키지가 있는가?
No!
21년도 6월 쯤이였는데, 그 때 당시에는 찾지 못했습니다.
(현재도 찾지 못했는데, 찾으신 패키지가 있다면 댓글로 알려주세요!)
직접 구현하여 가능한가?
Maybe?....
Web의 css에서는 유니코드 범위를 통해 다른 폰트를 적용하고 있었습니다.
여기서 아이디어를 얻어 텍스트를 파싱 후 동적으로 RichText를 구현하기로 결정하고, 디자이너분께 가능하다고 말씀드렸어요.
이제 문제가 더 명확해졌습니다.
UI 작업을 더 효율적으로 하기 위해 디자인 시스템을 만드는 것이므로, 이 동적인 Text 위젯은 기본 Text 위젯만큼 사용하기 편하게 만들어야 합니다.
저희 앱에 최적화하여 별다른 세팅없이 사용할 수 있도록, 로직에 폰트 설정들을 녹여서, Text 위젯처럼 쉽게 사용했습니다.
최근 또 다른 프로젝트에 디자인 시스템을 미리 적용하면서,
동일한 요구사항이 생겼습니다.
그래서 코드 복붙의 귀찮음 + 다른 개발자를 생각하는 오지랖이 합쳐져 이번 추석 연휴 기간에 패키지나 만들자 생각하고 실행에 옮깁니다
그렇게 Xtyle이 만들어집니다.
Multiligual-style 👉 X-style 👉 Xtyle (엑스타일)
기존 프로젝트에서 패키지화 하면서 변경되는 부분은 크게 다음과 같습니다.
Super프리미엄 리미티드Edition 텍스트를 크기 16, 검정색을 적용하려면 기본 Text 위젯으로는 다음과 같은 위젯을 만듭니다.
Text(
'Super프리미엄 리미티드Edition',
style: TextStyle(fontSize: 16.0, color: Colors.black),
)
이제 Super, Edition 은 영문 폰트를, 프리미엄, 리미티드는 한글 폰트를 적용하기 위해 Xtyle에서 제공하는 위젯을 사용하면 다음과 같습니다.
XtyleText(
'Super프리미엄 리미티드Edition',
style: TextStyle(fontSize: 16.0, color: Colors.black),
)
어떠한 파라미터 변경도 없이 Text위젯을 XtyleText위젯으로 변경하면 끝입니다.

먼저 앱 전체에 적용할 설정 값을 main.dart 에서 runApp 호출 전에 초기화해야 합니다.
// main.dart
import 'package:xtyle/xtyle.dart';
void main() {
...
Xtyle.init(
configuration: XtyleConfig.korean(
fontFamilyKor: 'NotoSans',
defaultFontFamily: 'Lato',
),
);
...
runApp(const MyApp());
}
XtyleConfig를 통해 적용할 언어와 해당 fontFamily 를 설정할 수 있습니다.
XtyleConfig는 다양한 방법을 통해 생성할 수 있습니다.
// 특정 세팅에 맞춰진 NamedConstructor 사용
// 한글만 다른 폰트를 적용하는 경우에 XtyleConfig.korean() 사용
final config = XtyleConfig.korean(
fontFamilyKor: 'NotoSans', // 한글 적용 폰트
defaultFontFamily: 'Lato', // 그 외 적용 폰트
);
// 직접 XtyleMapper를 만들어서 사용할 수 있습니다.
// 한글, 영숫자에 각각 다른 폰트 적용
final config = XtyleConfig(
mapper: {
XtyleRegExp.korean: 'NotoSans', // 한글 적용 폰트
XtyleRegExp.alphanumeric: 'Lato', // 영문+숫자 적용 폰트
},
defaultFontFamily: 'Roboto' // 그 외 적용 폰트
);
// Builder 패턴을 통한 생성도 가능합니다.
// 한글, 영숫자에 각각 다른 폰트 적용
final config = XtyleConfig.builder()
.addMapping(XtyleRegExp.korean, 'NotoSans')
.addMapping(XtyleRegExp.alphanumeric, 'Lato')
.setDefaultFontFamily('Roboto');
Mapper를 잘 보셨다면, 대충 눈치채셨으리라 생각합니다. XtyleMapper 는 Map<RegExp, String> Type 입니다.
Xtyle은 정규표현식을 통해 Unicode Range를 검사하여 해당 영역에 스타일을 변경합니다.
XtyleRegExp.korean = RegExp(r'[ㄱ-ㅣ가-힣]');
제공되는 XtyleRegExp.korean을 보면 [ㄱ-ㅣ가-힣]으로 범위가 설정되어 있습니다.
만약, 영어 대문자 / 소문자에 적용되는 폰트를 다르게 하고 싶다면
{
RegExp(r'[a-z]'): 'NotoSans',
RegExp(r'[A-Z]'): 'Lato',
}
이렇게 커스텀한 Mapper를 사용할 수 있습니다.
TextField, TextFormField 위젯은 별도로 Xtyle 위젯이 없습니다.
TextEditingController를 통해 스타일링이 가능한 점을 이용하여 Xtyle이 적용되는 XtyleTextController를 사용할 수 있습니다.
TextField(
controller: XtyleTextController(),
...
)
초기 버전은 한글, 영문 사용에 초점을 두고 배포했습니다.
추가 언어에 대한 XtyleRegExp 를 커뮤니티의 힘을 빌려 이슈나 PR을 통해 지속적 추가할 계획입니다.
와! 딱 필요한 패키지였습니다!! 감사히 잘쓰겠습니다^^