Compose의 Material 2에서 Material 3으로 이전

Material Design 3은 차세대 Material Design입니다. 업데이트된 테마 설정, 구성요소, Material You 맞춤설정 기능(동적 색상 등)을 포함합니다. Material Design 2의 업데이트이며 Android 12 이상의 새로운 시각적 스타일 및 시스템 UI와 일관됩니다.

이 가이드에서는 Compose Material(androidx.compose.material) Jetpack 라이브러리에서 Compose Material 3(androidx.compose.material3) Jetpack 라이브러리로의 이전을 중점적으로 설명합니다.

접근 방식

일반적으로 하나의 앱에서 M2와 M3 둘 다를 장기적으로 사용해서는 안 됩니다. 이는 두 디자인 시스템과 각 라이브러리가 UX/UI 디자인 및 Compose 구현 측면에서 크게 다르기 때문입니다.

앱이 Figma를 통해 만들어진 것과 같은 디자인 시스템을 사용할 수도 있습니다. 이러한 경우 Compose 이전을 시작하기 전에 개발자 또는 디자인팀이 M2에서 M3으로 이전하는 것이 좋습니다. UX/UI 디자인이 M2를 기반으로 하는 경우 앱을 M3으로 이전하는 것은 의미가 없습니다.

또한 앱의 크기, 복잡성, UX/UI 디자인에 따라 이전 접근 방식이 달라야 합니다. 그러면 코드베이스에 미치는 영향을 최소화할 수 있습니다. 따라서 단계적인 접근 방식을 사용해야 합니다.

이전 시기

가능한 한 빨리 이전을 시작해야 합니다. 그러나 앱이 M2에서 M3으로 완전히 이전할 현실적인 상황인지 고려하는 것이 중요합니다. 시작하기 전에 조사할 만한 차단 시나리오는 다음과 같습니다.

시나리오 권장 방법
차단된 항목 없음 단계적 이전 시작
M2의 구성요소를 아직 M3에서 사용할 수 없습니다. 아래의 구성요소 및 레이아웃 섹션을 참고하세요. 단계적 이전 시작
개발자 또는 디자인팀이 앱의 디자인 시스템을 M2에서 M3으로 이전하지 않았습니다. 디자인 시스템을 M2에서 M3으로 이전한 후 단계적 이전 시작

위의 시나리오에 해당하더라도 앱 업데이트를 커밋하고 출시하기 전에 단계적인 접근 방식을 취해야 합니다. 이 경우 M2와 M3을 나란히 사용하고 M3으로 이전하는 동안 점진적으로 M2를 단계적으로 중단합니다.

단계적 접근 방식

단계적인 이전의 일반적인 과정은 다음과 같습니다.

  1. M2 종속 항목과 함께 M3 종속 항목을 추가합니다.
  2. 앱 테마의 M2 버전과 함께 앱 테마의 M3 버전을 추가합니다.
  3. 앱의 크기와 복잡성에 따라 개별 모듈, 화면 또는 컴포저블을 M3으로 이전합니다(자세한 내용은 아래 섹션 참고).
  4. 완전히 이전되면 앱 테마의 M2 버전을 삭제합니다.
  5. M2 종속 항목을 삭제합니다.

종속 항목

M3에는 M2와 별개인 패키지 및 버전이 있습니다.

M2

implementation "androidx.compose.material:material:$m2-version"

M3

implementation "androidx.compose.material3:material3:$m3-version"

Compose Material 3 출시 페이지에서 최신 M3 버전을 참고하세요.

기본 M2 및 M3 라이브러리 외의 다른 Material 종속 항목은 변경되지 않았습니다. M2 패키지와 M3 패키지 및 버전을 함께 사용하지만, 이는 이전에 영향을 주지 않습니다. M3에서 그대로 사용할 수 있습니다.

라이브러리 패키지 및 버전
Compose Material 아이콘 androidx.compose.material:material-icons-*:$m2-version
Compose 머티리얼 물결 효과 androidx.compose.material:material-ripple:$m2-version

실험용 API

일부 M3 API는 실험용으로 간주됩니다. 이러한 경우 ExperimentalMaterial3Api 주석을 사용하여 함수 또는 파일 수준에서 선택해야 합니다.

import androidx.compose.material3.ExperimentalMaterial3Api

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppComposable() {
    // M3 composables
}

테마 설정

M2와 M3에서 테마 컴포저블의 이름은 MaterialTheme이지만 가져오기 패키지와 매개변수는 다음과 같이 다릅니다.

M2

import androidx.compose.material.MaterialTheme

MaterialTheme(
    colors = AppColors,
    typography = AppTypography,
    shapes = AppShapes
) {
    // M2 content
}

M3

import androidx.compose.material3.MaterialTheme

MaterialTheme(
    colorScheme = AppColorScheme,
    typography = AppTypography,
    shapes = AppShapes
) {
    // M3 content
}

색상

M2 색상과 M3 색상 시스템 비교
그림 1. M2 색상 시스템 (왼쪽)과 M3 색상 시스템 (오른쪽) 비교

M3의 색상 시스템은 M2와 매우 다릅니다. 색상 매개변수의 수가 많아졌고 이름도 다르며 M3 구성요소에 다른 방식으로 매핑됩니다. Compose에서 이는 M2 Colors 클래스, M3 ColorScheme 클래스 및 관련 함수에 적용됩니다.

M2

import androidx.compose.material.lightColors
import androidx.compose.material.darkColors

val AppLightColors = lightColors(
    // M2 light Color parameters
)
val AppDarkColors = darkColors(
    // M2 dark Color parameters
)
val AppColors = if (darkTheme) {
    AppDarkColors
} else {
    AppLightColors
}

M3

import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme

val AppLightColorScheme = lightColorScheme(
    // M3 light Color parameters
)
val AppDarkColorScheme = darkColorScheme(
    // M3 dark Color parameters
)
val AppColorScheme = if (darkTheme) {
    AppDarkColorScheme
} else {
    AppLightColorScheme
}

M2 색상 시스템과 M3 색상 시스템 사이의 큰 차이를 고려할 때 Color 매개변수의 적절한 매핑은 없습니다. 대신 머티리얼 테마 빌더 도구를 사용하여 M3 색 구성표를 생성합니다. 이 도구는 M2 색상을 핵심 소스 색상으로 사용하며 M3 색 구성표에 사용되는 색조 팔레트로 확장합니다. 다음 매핑을 시작점으로 사용하는 것이 좋습니다.

M2 Material 테마 빌더
primary 기본
primaryVariant 보조
secondary 3차
surface 또는 background 보통
머티리얼 테마 빌더에서 M3 색 구성표를 생성하는 데 사용되는 M2 색상
그림 2. 머티리얼 테마 빌더에서 M3 색 구성표를 생성하는 데 사용되는 Jetchat의 M2 색상

도구에서 밝은 테마와 어두운 테마의 색상 16진수 코드 값을 복사하여 M3 ColorScheme 인스턴스를 구현하는 데 사용할 수 있습니다. 또는 머티리얼 테마 빌더에서 Compose 코드를 내보낼 수 있습니다.

isLight

M2 Colors 클래스와 달리 M3 ColorScheme 클래스에는 isLight 매개변수가 없습니다. 일반적으로 이 정보가 필요한 항목을 테마 수준에서 모델링해야 합니다. 예를 들면 다음과 같습니다.

M2

import androidx.compose.material.lightColors
import androidx.compose.material.darkColors
import androidx.compose.material.MaterialTheme

@Composable
private fun AppTheme(
  darkTheme: Boolean = isSystemInDarkTheme(),
  content: @Composable () -> Unit
) {
  val colors = if (darkTheme) darkColors(…) else lightColors(…)
  MaterialTheme(
      colors = colors,
      content = content
  )
}

@Composable
fun AppComposable() {
    AppTheme {
        val cardElevation = if (MaterialTheme.colors.isLight) 0.dp else 4.dp
        …
    }
}

M3

import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.MaterialTheme

val LocalCardElevation = staticCompositionLocalOf { Dp.Unspecified }
@Composable
private fun AppTheme(
   darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
   val cardElevation = if (darkTheme) 4.dp else 0.dp
    CompositionLocalProvider(LocalCardElevation provides cardElevation) {
        val colorScheme = if (darkTheme) darkColorScheme(…) else lightColorScheme(…)
        MaterialTheme(
            colorScheme = colorScheme,
            content = content
        )
    }
}

@Composable
fun AppComposable() {
    AppTheme {
        val cardElevation = LocalCardElevation.current
        …
    }
}

자세한 내용은 Compose의 맞춤 디자인 시스템 가이드를 참고하세요.

동적 색상

M3의 새로운 기능은 동적 색상입니다. 맞춤 색상을 사용하는 대신 M3 ColorScheme은 Android 12 이상에서 다음 함수를 사용하여 기기 배경화면 색상을 활용할 수 있습니다.

서체

M2와 M3 서체 시스템 비교
그림 3. M3 서체 시스템 (왼쪽)과 M2 서체 시스템 (오른쪽) 비교

M3의 서체 시스템은 M2와 다릅니다. 서체 매개변수의 수는 거의 동일하지만 이름이 다르며 M3 구성요소에 다르게 매핑됩니다. Compose에서 이는 M2 Typography 클래스와 M3 Typography 클래스에 적용됩니다.

M2

import androidx.compose.material.Typography

val AppTypography = Typography(
    // M2 TextStyle parameters
)

M3

import androidx.compose.material3.Typography

val AppTypography = Typography(
    // M3 TextStyle parameters
)

다음 TextStyle 매개변수 매핑을 시작점으로 사용하는 것이 좋습니다.

M2 M3
h1 displayLarge
h2 displayMedium
h3 displaySmall
N/A headlineLarge
h4 headlineMedium
h5 headlineSmall
h6 titleLarge
subtitle1 titleMedium
subtitle2 titleSmall
body1 bodyLarge
body2 bodyMedium
caption bodySmall
button labelLarge
해당 사항 없음 labelMedium
overline labelSmall

도형

M2와 M3 도형 시스템 비교
그림 4. M2 도형 시스템 (왼쪽)과 M3 도형 시스템 (오른쪽) 비교

M3의 도형 시스템은 M2와 다릅니다. 도형 매개변수의 수가 많아졌고 이름이 다르게 지정되었으며 M3 구성요소에 다르게 매핑됩니다. Compose에서 이는 M2 Shapes 클래스와 M3 Shapes 클래스에 적용됩니다.

M2

import androidx.compose.material.Shapes

val AppShapes = Shapes(
    // M2 Shape parameters
)

M3

import androidx.compose.material3.Shapes

val AppShapes = Shapes(
    // M3 Shape parameters
)

다음 Shape 매개변수 매핑을 시작점으로 사용하는 것이 좋습니다.

M2 M3
N/A extraSmall
small small
medium medium
large large
해당 사항 없음 extraLarge

구성요소 및 레이아웃

M2의 구성요소와 레이아웃은 대부분 M3에서 사용할 수 있습니다. 그러나 M2에 없는 새로운 기능과 누락된 항목도 있습니다. 또한 일부 M3 구성요소에는 상응하는 M2 요소보다 더 많은 변형이 있습니다. 일반적으로 M3 API 노출 영역은 가장 가깝게 상응하는 M2 항목에 최대한 비슷하게 시도합니다.

업데이트된 색상, 서체, 도형 시스템을 고려하여 M3 구성요소는 새로운 테마 설정 값에 다르게 매핑되는 경향이 있습니다. 이러한 매핑의 정보 소스로 Compose Material 3 소스 코드의 토큰 디렉터리를 확인하는 것이 좋습니다.

일부 구성요소에는 특별한 고려사항이 필요하지만, 다음과 같은 함수 매핑을 시작점으로 사용하는 것이 좋습니다.

누락 API:

M2 M3
androidx.compose.material.swipeable 아직 사용할 수 없음

대체된 API:

M2 M3
androidx.compose.material.BackdropScaffold 상응하는 M3 항목 없음. 대신 Scaffold 또는 BottomSheetScaffold로 이전
androidx.compose.material.BottomDrawer 상응하는 M3 항목 없음. 대신 ModalBottomSheet로 이전

이름 변경된 API:

M2 M3
androidx.compose.material.BottomNavigation androidx.compose.material3.NavigationBar
androidx.compose.material.BottomNavigationItem androidx.compose.material3.NavigationBarItem
androidx.compose.material.Chip androidx.compose.material3.AssistChip 또는 androidx.compose.material3.SuggestionChip
androidx.compose.material.ModalBottomSheetLayout androidx.compose.material3.ModalBottomSheet
androidx.compose.material.ModalDrawer androidx.compose.material3.ModalNavigationDrawer

기타 모든 API:

M2 M3
androidx.compose.material.AlertDialog androidx.compose.material3.AlertDialog
androidx.compose.material.Badge androidx.compose.material3.Badge
androidx.compose.material.BadgedBox androidx.compose.material3.BadgedBox
androidx.compose.material.BottomAppBar androidx.compose.material3.BottomAppBar
androidx.compose.material.BottomSheetScaffold androidx.compose.material3.BottomSheetScaffold
androidx.compose.material.Button androidx.compose.material3.Button
androidx.compose.material.Card androidx.compose.material3.Card
androidx.compose.material.Checkbox androidx.compose.material3.Checkbox
androidx.compose.material.CircularProgressIndicator androidx.compose.material3.CircularProgressIndicator
androidx.compose.material.Divider androidx.compose.material3.Divider
androidx.compose.material.DropdownMenu androidx.compose.material3.DropdownMenu
androidx.compose.material.DropdownMenuItem androidx.compose.material3.DropdownMenuItem
androidx.compose.material.ExposedDropdownMenuBox androidx.compose.material3.ExposedDropdownMenuBox
androidx.compose.material.ExtendedFloatingActionButton androidx.compose.material3.ExtendedFloatingActionButton
androidx.compose.material.FilterChip androidx.compose.material3.FilterChip
androidx.compose.material.FloatingActionButton androidx.compose.material3.FloatingActionButton
androidx.compose.material.Icon androidx.compose.material3.Icon
androidx.compose.material.IconButton androidx.compose.material3.IconButton
androidx.compose.material.IconToggleButton androidx.compose.material3.IconToggleButton
androidx.compose.material.LeadingIconTab androidx.compose.material3.LeadingIconTab
androidx.compose.material.LinearProgressIndicator androidx.compose.material3.LinearProgressIndicator
androidx.compose.material.ListItem androidx.compose.material3.ListItem
androidx.compose.material.NavigationRail androidx.compose.material3.NavigationRail
androidx.compose.material.NavigationRailItem androidx.compose.material3.NavigationRailItem
androidx.compose.material.OutlinedButton androidx.compose.material3.OutlinedButton
androidx.compose.material.OutlinedTextField androidx.compose.material3.OutlinedTextField
androidx.compose.material.RadioButton androidx.compose.material3.RadioButton
androidx.compose.material.RangeSlider androidx.compose.material3.RangeSlider
androidx.compose.material.Scaffold androidx.compose.material3.Scaffold
androidx.compose.material.ScrollableTabRow androidx.compose.material3.ScrollableTabRow
androidx.compose.material.Slider androidx.compose.material3.Slider
androidx.compose.material.Snackbar androidx.compose.material3.Snackbar
androidx.compose.material.Switch androidx.compose.material3.Switch
androidx.compose.material.Tab androidx.compose.material3.Tab
androidx.compose.material.TabRow androidx.compose.material3.TabRow
androidx.compose.material.Text androidx.compose.material3.Text
androidx.compose.material.TextButton androidx.compose.material3.TextButton
androidx.compose.material.TextField androidx.compose.material3.TextField
androidx.compose.material.TopAppBar androidx.compose.material3.TopAppBar
androidx.compose.material.TriStateCheckbox androidx.compose.material3.TriStateCheckbox

Compose Material 3 API 참조 개요에서 최신 M3 구성요소 및 레이아웃을 확인하고 출시 페이지에서 신규 및 업데이트된 API를 확인하세요.

스캐폴드, 스낵바, 탐색 창

스낵바 및 탐색 창이 포함된 M2 및 M3 스캐폴드 비교
그림 5. 스낵바 및 탐색 창이 있는 M2 스캐폴드 (왼쪽)와 스낵바 및 탐색 창이 있는 M3 스캐폴드 (오른쪽)

M3의 스캐폴드는 M2와 다릅니다. M2와 M3에서 기본 레이아웃 컴포저블의 이름은 Scaffold이지만 가져오기 패키지와 매개변수는 다음과 같이 다릅니다.

M2

import androidx.compose.material.Scaffold

Scaffold(
    // M2 scaffold parameters
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    // M3 scaffold parameters
)

이제 M2 ScaffoldbackgroundColor 매개변수가 포함되며, 이 매개변수는 M3 Scaffold에서 containerColor로 이름이 지정됩니다.

M2

import androidx.compose.material.Scaffold

Scaffold(
    backgroundColor = …,
    content = { … }
)

M3

import androidx.compose.material3.Scaffold

Scaffold(
    containerColor = …,
    content = { … }
)

M2 ScaffoldState 클래스는 더 이상 필요하지 않은 drawerState 매개변수를 포함하므로 더 이상 M3에 없습니다. M3 Scaffold로 스낵바를 표시하려면 대신 SnackbarHostState를 사용합니다.

M2

import androidx.compose.material.Scaffold
import androidx.compose.material.rememberScaffoldState

val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()

Scaffold(
    scaffoldState = scaffoldState,
    content = {
        …
        scope.launch {
            scaffoldState.snackbarHostState.showSnackbar(…)
        }
    }
)

M3

import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState

val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()

Scaffold(
    snackbarHost = { SnackbarHost(snackbarHostState) },
    content = {
        …
        scope.launch {
            snackbarHostState.showSnackbar(…)
        }
    }
)

M2 Scaffold의 모든 drawer* 매개변수가 M3 Scaffold에서 삭제되었습니다. 여기에는 drawerShapedrawerContent와 같은 매개변수가 포함됩니다. M3 Scaffold로 창을 표시하려면 대신 ModalNavigationDrawer와 같은 탐색 창 컴포저블을 사용합니다.

M2

import androidx.compose.material.DrawerValue
import
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberDrawerState
import androidx.compose.material.rememberScaffoldState

val scaffoldState = rememberScaffoldState(
    drawerState = rememberDrawerState(DrawerValue.Closed)
)
val scope = rememberCoroutineScope()

Scaffold(
    scaffoldState = scaffoldState,
    drawerContent = { … },
    drawerGesturesEnabled = …,
    drawerShape = …,
    drawerElevation = …,
    drawerBackgroundColor = …,
    drawerContentColor = …,
    drawerScrimColor = …,
    content = {
        …
        scope.launch {
            scaffoldState.drawerState.open()
        }
    }
)

M3

import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.rememberDrawerState

val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()

ModalNavigationDrawer(
    drawerState = drawerState,
    drawerContent = {
        ModalDrawerSheet(
            drawerShape = …,
            drawerTonalElevation = …,
            drawerContainerColor = …,
            drawerContentColor = …,
            content = { … }
        )
    },
    gesturesEnabled = …,
    scrimColor = …,
    content = {
        Scaffold(
            content = {
                …
                scope.launch {
                    drawerState.open()
                }
            }
        )
    }
)

상단 앱 바

상단 앱 바와 스크롤 목록이 포함된 M2 및 M3 스캐폴드 비교
그림 6. 상단 앱 바와 스크롤 목록이 있는 M2 스캐폴드 (왼쪽)와 상단 앱 바와 스크롤 목록이 있는 M3 스캐폴드 (오른쪽)

M3의 상단 앱 바는 M2와 다릅니다. M2와 M3에서 상단 앱 바 기본 컴포저블의 이름은 TopAppBar이지만 가져오기 패키지와 매개변수는 다음과 같이 다릅니다.

M2

import androidx.compose.material.TopAppBar

TopAppBar(…)

M3

import androidx.compose.material3.TopAppBar

TopAppBar(…)

이전에 M2 TopAppBar 내에서 콘텐츠를 중앙에 배치했다면 M3 CenterAlignedTopAppBar를 사용하는 것이 좋습니다. MediumTopAppBarLargeTopAppBar도 유의하는 것이 좋습니다.

M3 상단 앱 바에는 TopAppBarScrollBehavior 클래스를 스크롤할 때 고도 변경과 같은 다양한 기능을 제공하는 새로운 scrollBehavior 매개변수가 포함되어 있습니다. 이는 Modifer.nestedScroll을 통한 콘텐츠 스크롤과 함께 작동합니다. M2 TopAppBar에서는 elevation 매개변수를 수동으로 변경하는 방법으로 가능했습니다.

M2

import androidx.compose.material.AppBarDefaults
import androidx.compose.material.Scaffold
import androidx.compose.material.TopAppBar

val state = rememberLazyListState()
val isAtTop by remember {
    derivedStateOf {
        state.firstVisibleItemIndex == 0 && state.firstVisibleItemScrollOffset == 0
    }
}

Scaffold(
    topBar = {
        TopAppBar(
            elevation = if (isAtTop) {
                0.dp
            } else {
                AppBarDefaults.TopAppBarElevation
            },
            …
        )
    },
    content = {
        LazyColumn(state = state) { … }
    }
)

M3

import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults

val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()

Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
    topBar = {
        TopAppBar(
            scrollBehavior = scrollBehavior,
            …
        )
    },
    content = {
        LazyColumn { … }
    }
)

하단 탐색/탐색 메뉴

M2 하단 탐색과 M3 탐색 메뉴 비교
그림 7. M2 하단 탐색 (왼쪽)과 M3 탐색 메뉴 (오른쪽) 비교

M2의 하단 탐색이 M3에서 탐색 메뉴로 이름이 바뀌었습니다. M2에는 BottomNavigationBottomNavigationItem 컴포저블이 있는 반면, M3에는 NavigationBarNavigationBarItem 컴포저블이 있습니다.

M2

import androidx.compose.material.BottomNavigation
import androidx.compose.material.BottomNavigationItem

BottomNavigation {
    BottomNavigationItem(…)
    BottomNavigationItem(…)
    BottomNavigationItem(…)
}

M3

import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem

NavigationBar {
    NavigationBarItem(…)
    NavigationBarItem(…)
    NavigationBarItem(…)
}

버튼, 아이콘 버튼, 플로팅 작업 버튼

M2 버튼과 M3 버튼 비교
그림 8. M2 버튼 (왼쪽)과 M3 버튼 (오른쪽) 비교

M3의 버튼, 아이콘 버튼, 플로팅 작업 버튼(FAB)은 M2의 버튼과 다릅니다. M3에는 M2 버튼 컴포저블이 모두 포함되어 있습니다.

M2

import androidx.compose.material.Button
import androidx.compose.material.ExtendedFloatingActionButton
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.IconButton
import androidx.compose.material.IconToggleButton
import androidx.compose.material.OutlinedButton
import androidx.compose.material.TextButton

// M2 buttons
Button(…)
OutlinedButton(…)
TextButton(…)
// M2 icon buttons
IconButton(…)
IconToggleButton(…)
// M2 FABs
FloatingActionButton(…)
ExtendedFloatingActionButton(…)

M3

import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconToggleButton
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.TextButton

// M3 buttons
Button(…)
OutlinedButton(…)
TextButton(…)
// M3 icon buttons
IconButton(…)
IconToggleButton(…)
// M3 FABs
FloatingActionButton(…)
ExtendedFloatingActionButton(…)

M3에는 새로운 버튼 변형도 있습니다. Compose Material 3 API 참조 개요에서 확인하세요.

전환

M2 스위치와 M3 스위치 비교
그림 9. M2 스위치 (왼쪽)와 M3 스위치 (오른쪽) 비교

M3의 스위치는 M2와 다릅니다. M2와 M3에서 스위치 컴포저블의 이름은 Switch이지만 가져오기 패키지는 서로 다릅니다.

M2

import androidx.compose.material.Switch

Switch(…)

M3

import androidx.compose.material3.Switch

Switch(…)

노출 영역 및 고도

밝은 테마와 어두운 테마에서 M2 노출 영역 고도와 M3 노출 영역 고도의 비교
그림 10. 밝은 테마 (왼쪽)와 어두운 테마 (오른쪽)에서 M2 노출 영역 고도와 M3 노출 영역 고도 비교

M3의 노출 영역 및 고도 시스템은 M2와 다릅니다. M3에는 두 가지 유형의 고도가 있습니다.

  • 그림자 고도(그림자 생성, M2와 동일)
  • 색조 고도(색상 오버레이, M3의 신규 기능)

Compose에서 이는 M2 Surface 함수와 M3 Surface 함수에 적용됩니다.

M2

import androidx.compose.material.Surface

Surface(
    elevation = …
) { … }

M3

import androidx.compose.material3.Surface

Surface(
    shadowElevation = …,
    tonalElevation = …
) { … }

UX/UI 디자인 환경설정에 따라 M3에서 shadowElevation 또는 tonalElevation에 모두 M2의 elevation Dp 값을 사용할 수 있습니다. Surface는 대부분의 구성요소를 뒷받침하는 지원 컴포저블이므로, 구성요소 컴포저블은 동일한 방식으로 이전해야 하는 고도 매개변수도 노출할 수 있습니다.

M3의 색조 고도는 M2 어두운 테마의 고도 오버레이 개념을 대체합니다. 따라서 ElevationOverlayLocalElevationOverlay는 M3에 없으며, M2의 LocalAbsoluteElevation는 M3에서 LocalAbsoluteTonalElevation으로 변경되었습니다.

강조 및 콘텐츠 알파

M2와 M3의 아이콘 및 텍스트 강조 비교
그림 11. M2 아이콘 및 텍스트 강조 (왼쪽)와 M3 아이콘 및 텍스트 강조 (오른쪽)

M3의 강조는 M2와 크게 다릅니다. M2에서 강조할 때는 텍스트 및 아이콘과 같은 콘텐츠를 구분하기 위해 특정 알파 값과 함께 on 색상을 사용합니다. 이제 M3에는 몇 가지 다른 접근 방식이 있습니다.

  • 확장된 M3 색상 시스템의 variant on 색상과 함께 on 색상 사용
  • 텍스트에 서로 다른 글꼴 두께 사용

따라서 ContentAlphaLocalContentAlpha는 M3에 없으며 대체해야 합니다.

다음 매핑을 시작점으로 사용하는 것이 좋습니다.

M2 M3
onSurfaceContentAlpha.high 일반적으로 onSurface. 텍스트의 경우 FontWeight.Medium - FontWeight.Black
onSurfaceContentAlpha.medium 일반적으로 onSurfaceVariant. 텍스트의 경우 FontWeight.Thin - FontWeight.Normal
onSurfaceContentAlpha.disabled onSurface.copy(alpha = 0.38f)

다음은 M2와 M3의 아이콘 강조를 보여주는 예입니다.

M2

import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha

// High emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
    Icon(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Icon(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Icon(…)
}

M3

import androidx.compose.material3.LocalContentColor

// High emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
    Icon(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant) {
    Icon(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)) {
    Icon(…)
}

다음은 M2와 M3의 텍스트 강조를 보여주는 예입니다.

M2

import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentAlpha

// High emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
    Text(…)
}
// Medium emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Text(…)
}
// Disabled emphasis
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Text(…)
}

M3

import androidx.compose.material3.LocalContentColor

// High emphasis
Text(
    …,
    fontWeight = FontWeight.Bold
)
// Medium emphasis
Text(
    …,
    fontWeight = FontWeight.Normal
)
// Disabled emphasis
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)) {
    Text(
        …,
        fontWeight = FontWeight.Normal
    )
}

배경 및 컨테이너

M2의 배경은 M3에서 컨테이너라고 부릅니다. 일반적으로 동일한 값을 사용하여 M2의 background* 매개변수를 M3에서 container*로 바꿀 수 있습니다. 예를 들면 다음과 같습니다.

M2

Badge(
    backgroundColor = MaterialTheme.colors.primary
) { … }

M3

Badge(
    containerColor = MaterialTheme.colorScheme.primary
) { … }

Compose에서 M2에서 M3으로 이전하는 방법에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.

문서

샘플 앱

동영상

API 참조 및 소스 코드