
defaultFontFamily, 다시 돌아왔어요
Material3 1.5 라인에서 다시 등장한 한 줄짜리 API인데, M3 초기에 빠졌던 바로 그 자리예요.
저는 그동안 displayLarge, headlineMedium, bodySmall … 13개 TextStyle 마다 fontFamily = Pretendard 를 일일이 복사해 박고 있었습니다. 두 줄씩 들어가니까 폰트 한 번 바꾸려면 26줄을 들춰야 했어요.
이번에는 이렇게 한 줄이면 끝나요.
val AppTypography = Typography(defaultFontFamily = Pretendard)
MaterialTheme(typography = AppTypography) { /* ... */ }
이전엔 이렇게 13개 스타일을 copy 로 돌려야 했죠.
val baseline = Typography()
val AppTypography = Typography(
displayLarge = baseline.displayLarge.copy(fontFamily = Pretendard),
displayMedium = baseline.displayMedium.copy(fontFamily = Pretendard),
// ... 나머지 스타일도 동일하게 copy
bodyLarge = baseline.bodyLarge.copy(fontFamily = Pretendard),
bodyMedium = baseline.bodyMedium.copy(fontFamily = Pretendard)
)
개별 TextStyle 에 fontFamily 가 지정돼 있으면 그 값이 우선이라, 기존 오버라이드는 그대로 살아 있어요. 특정 화면만 다른 폰트로 가고 싶을 땐 MaterialTheme 을 중첩하거나 LocalTypography provides ... 로 감싸면 됩니다. 본문은 Pretendard, 헤더만 노토 산스 KR(Noto Sans KR) 로 분기하는 식이 진짜 깔끔하게 빠지더라고요.
다만 한 가지 짚어둘 점은, 이 defaultFontFamily 는 아직 Material3 1.5.0-alpha 단계라는 거예요. 뒤에 나올 새 그림자(stable 트랙)와 달리 정식 안정화 전이라, 저는 stable 모듈에 바로 박기보다 alpha 트랙을 따라가는 모듈 쪽에 먼저 올려두고 1.5 가 베타·stable 로 굳는 시점을 보고 본체로 옮길 생각입니다.
가변 폰트(variable font) 를 쓰실 때는 일부 OEM 기기에서 굵기가 두꺼운 한 단계로 뭉개지는 일이 있었습니다. Font(weight = FontWeight.W500) 처럼 가중치를 명시한 Font 인스턴스를 FontFamily 안에 함께 등록해두니 그 문제는 사라졌어요.

Glance 위젯 unit-testing 으로 호스트 없이 회귀 검증
이번 BOM 묶음에 같이 올라온 androidx.glance:glance-appwidget-testing 도 잠깐 다뤄볼 만합니다.
runGlanceAppWidgetUnitTest 를 쓰면 실제 런처에 위젯을 올리지 않고도 위젯 렌더링을 단언할 수 있어요.
@Test
fun widgetShowsTitle() = runGlanceAppWidgetUnitTest {
provideComposable { MyHomeWidget(title = "오늘 할 일") }
onNode(hasTestTag("widget_title")).assertHasText("오늘 할 일")
}
호스트 앱을 띄우고 위젯을 잡아 늘리던 수동 검증이 통째로 사라져서, 제 CI 시간이 한 케이스당 30~40초 정도 짧아졌습니다.
SharedPreferences 같은 외부 의존성은 Fake DataStore 를 주입해야 하는 번거로움이 있긴 한데, BOM 버전업할 때마다 위젯 렌더링이 깨지는지 자동으로 잡아주는 회귀 테스트로서는 값을 톡톡히 합니다.

그래서, 어디부터 끼울까
저는 결국 사이드 앱 본체엔 stable BOM 을 유지하고, MeshGradient 가 들어간 헤더 모듈만 alpha BOM 으로 분리해 멀티 모듈로 가져갔습니다. 한 모듈 안에서 두 BOM 을 섞을 순 없지만, 모듈을 잘라두면 alpha 의 깨짐이 본체로 번지지 않거든요.
새 그림자(dropShadow / innerShadow) 는 이미 stable 트랙(1.11) 에 들어와 있어 가장 부담이 적고, defaultFontFamily 는 아직 Material3 1.5 alpha 라 그다음 순서로 두기 좋아요. MeshGradient 만은 다음 alpha 한두 번 더 묵혀보고, 1.12 가 베타로 떨어질 즈음에 본격 도입을 결정할 생각이에요.

26줄을 한 줄로 줄여놓고 git diff 화면을 멍하니 바라보던 그 새벽, 모니터 빛에 졸음이 가시던 그 감각이 사실 이 글을 쓰게 만든 진짜 이유였습니다.
'Android 개발 > Jetpack Compose' 카테고리의 다른 글
| 안드로이드 위젯 통합 테스트, remote-testing으로 뚫린 사각지대 (0) | 2026.06.03 |
|---|---|
| MeshGradient Modifier, 한 줄로 끝난다는 말의 진짜 의미 (0) | 2026.05.30 |
| Material3 1.5.0-alpha19 adaptive pane scaffold, 1.5.0 안정 직전 정리 (0) | 2026.05.19 |
| 최근 안정화된 Compose API, MeshGradient 말고 매일 쓸 3가지 (0) | 2026.05.13 |
| Jetpack Compose 업데이트, 진짜 '물건'은 따로 있었네요 (0) | 2026.05.10 |