TopAppBar: Jetpack Compose에서의 개념, 설정 및 사용법

저자: IT Sectr 게시일: 2026-06-29 읽는 시간: 8 분

TopAppBar는 제목, 탐색 버튼 및 추가 작업이 포함된 상단 앱 바를 표시하는 Material Design 구성 요소입니다. Jetpack Compose에서 TopAppBar는 Material 라이브러리의 TopAppBar 컴포저블 함수를 통해 구현됩니다. 공식 Android Developers 문서(2025)에 따르면 TopAppBar는 Material2와 Material3를 지원하며, 적응형 높이, 색상 및 애니메이션을 포함합니다. 바는 시스템 상태 표시줄에 자동으로 적응하고 Insets와 올바르게 작동합니다. TopAppBar는 Android 애플리케이션에서 탐색 및 상황별 작업의 주요 진입점으로 사용됩니다.

주요 포인트

  • TopAppBar는 Jetpack Compose의 상단 앱 바를 위한 Material Design 컴포저블 구성 요소입니다
  • 매개변수에는 유연한 사용자 지정을 위한 title, navigationIcon, actions 및 수정자가 포함됩니다
  • Material3는 다이나믹 컬러 및 적응형 여백 지원과 함께 TopAppBar를 제공합니다
  • 탐색 버튼은 Drawer를 열거나 이전 화면으로 돌아가는 데 사용됩니다
  • ScrollBehavior를 사용하면 공간을 절약하기 위해 콘텐츠를 스크롤할 때 TopAppBar를 숨길 수 있습니다

Jetpack Compose에서 TopAppBar란?

TopAppBar는 Jetpack Compose용 Material Design 라이브러리의 컴포저블 함수로, 상단 앱 바를 구현합니다. 이 구성 요소는 현재 화면의 제목, 왼쪽의 탐색 버튼 및 오른쪽의 추가 작업을 표시합니다.

기존 View 시스템과 달리 Compose 버전의 TopAppBar는 완전히 선언적입니다. findViewById를 통해 관리되는 대신 상태가 변경될 때 바가 다시 그려집니다. TopAppBar는 슬롯 API 개념을 사용하며, title, navigationIcon 및 actions가 컴포저블 람다로 전달됩니다. 이를 통해 상속 없이 바의 모든 요소를 사용자 지정할 수 있습니다.

Google Material Design(2025)에 따르면 Compose의 TopAppBar는 세 가지 유형으로 제공됩니다: CenterAlignedTopAppBar(중앙 정렬 제목), SmallTopAppBar(표준), MediumTopAppBar(확장). 각 유형은 바 높이, 제목 글꼴 크기 및 스크롤 동작을 정의합니다. 중앙 정렬 변형은 주 화면에서 더 자주 사용되며, MediumTopAppBar는 스크롤 시 제목이 부드럽게 축소되는 콘텐츠 페이지에 사용됩니다.

TopAppBar의 올바른 작동을 위해 시스템 여백(WindowInsetsCompat의 Insets)을 고려해야 합니다. Android Developers(2025)의 권장 사항에 따르면 Modifier.statusBarsPadding() 또는 windowInsetsPadding(WindowInsets.systemBars)을 호출하면 바가 상태 표시줄과 겹치는 것을 방지할 수 있습니다.

TopAppBar 매개변수: 제목 및 수정자 구성

TopAppBar 구성 요소는 여러 필수 및 선택적 매개변수를 허용합니다. 주요 매개변수는 title로, 제목 텍스트가 포함된 컴포저블 블록이 전달됩니다. title은 @Composable 람다이므로 텍스트뿐만 아니라 아이콘과 텍스트, 검색 필드 생성 또는 진행률 표시도 가능합니다.

kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppTopBar() {
    TopAppBar(
        title = { Text("Main") },
        navigationIcon = {
            IconButton(onClick = { /* open drawer */ }) {
                Icon(
                    Icons.Filled.Menu,
                    contentDescription = "Menu"
                )
            }
        },
        actions = {
            IconButton(onClick = { /* search */ }) {
                Icon(Icons.Filled.Search, contentDescription = "Search")
            }
        }
    )
}

Modifier 매개변수를 사용하면 전체 바의 패딩, 크기 및 정렬을 설정할 수 있습니다. Modifier.heightIn을 통해 최소 및 최대 높이를 제한할 수 있습니다. colors 매개변수는 배경, 제목 및 아이콘 색상을 재정의하는 TopAppBarColors 개체를 허용합니다.

기본적으로 TopAppBar는 현재 MaterialTheme의 색 구성표를 사용합니다. 사용자 지정 팔레트가 필요한 경우 TopAppBarDefaults.smallTopAppBarColors()를 사용합니다. Material3에서는 밝은 테마와 어두운 테마에서 배경색이 자동으로 surfaceColor에 적응하므로 수동 구성이 필요하지 않습니다.

매개변수유형설명
title@Composable () -> Unit바의 제목 블록
navigationIcon@Composable () -> Unit탐색 아이콘(햄버거/화살표)
actions@Composable RowScope.() -> Unit오른쪽의 작업 블록
scrollBehaviorTopAppBarScrollBehavior?스크롤 동작
colorsTopAppBarColors바의 색 구성표

NavigationIcon은 TopAppBar의 왼쪽 부분에 있는 컴포저블 블록으로, 이를 통해 탐색이 구현됩니다. 일반적인 시나리오: Navigation Drawer 열기(메뉴 아이콘), 이전 화면으로 돌아가기(ArrowBack 아이콘), 현재 화면 닫기(닫기 아이콘).

아이콘 선택은 탐색 스택에서 화면의 위치에 따라 달라집니다. 화면이 루트인 경우 Drawer를 열기 위해 메뉴 아이콘이 표시됩니다. 화면이 중첩된 경우 돌아가기 위해 ArrowBack 아이콘이 표시됩니다. Compose에서 이 로직은 NavController를 통해 구현됩니다. 현재 백 스택 항목이 표시할 아이콘을 결정합니다.

Material Design(2025) 권장 사항에 따르면 탐색 영역의 너비는 48 dp로, 터치 상호 작용의 표준 대상입니다. 아이콘은 시각적 피드백(ripple)과 함께 클릭 가능해야 합니다. Compose에서는 탐색을 트리거하는 onClick 콜백이 있는 IconButton으로 래핑하여 보장합니다.

Scaffold를 사용할 때 탐색 버튼은 TopAppBar에 직접 전달되지 않고 Scaffold에 전달되는 DrawerState를 복제할 수 있습니다. 이 경우 navigationIcon은 rememberDrawerState를 통해 Drawer 상태를 참조합니다.

액션 및 드롭다운 메뉴 추가

TopAppBar의 actions 매개변수는 RowScope 컨텍스트가 있는 컴포저블 블록을 허용하여 제목 오른쪽에 여러 아이콘이나 버튼을 배치할 수 있습니다. 각 액션은 클릭 가능한 아이콘 요소(검색, 알림, 설정, 즐겨찾기)여야 합니다.

오버플로 액션의 경우 DropdownMenu를 통해 드롭다운 메뉴가 사용됩니다. 액션 수가 3개를 초과하면 추가 액션이 MoreVert 아이콘과 함께 OverflowMenu에 배치됩니다. 클릭하면 숨겨진 액션 목록이 열립니다. DropdownMenu는 아이콘을 기준으로 자동으로 배치됩니다.

kotlin
@Composable
fun TopBarWithOverflow() {
    var menuExpanded by remember { mutableStateOf(false) }
    TopAppBar(
        title = { Text("Profile") },
        actions = {
            IconButton(onClick = { /* share */ }) {
                Icon(Icons.Filled.Share, contentDescription = "Share")
            }
            Box {
                IconButton(onClick = { menuExpanded = true }) {
                    Icon(Icons.Filled.MoreVert, contentDescription = "More")
                }
                DropdownMenu(
                    expanded = menuExpanded,
                    onDismissRequest = { menuExpanded = false }
                ) {
                    DropdownMenuItem(text = { Text("Settings") }, onClick = { /* navigate */ })
                    DropdownMenuItem(text = { Text("About") }, onClick = { /* navigate */ })
                }
            }
        }
    )
}

각 아이콘에 contentDescription을 설정하는 것이 중요합니다. 이는 접근성 요구 사항입니다. 설명이 없으면 TalkBack이 버튼을 읽어주지 않습니다. 순전히 장식용 요소의 경우 contentDescription = null을 사용합니다.

Material3의 TopAppBar: 다이나믹 컬러 및 적응

Material3(M3)는 Material Design의 현재 버전으로, Google이 새 프로젝트에 권장합니다. M3의 TopAppBar는 TopAppBar, CenterAlignedTopAppBarMediumTopAppBar를 통해 구현됩니다. Material2와의 주요 차이점은 다이나믹 컬러, 적응형 높이 및 스크롤 동작에 대한 기본 제공 지원입니다.

다이나믹 컬러는 기기 배경화면(Android 12+)을 기반으로 바 색상을 자동으로 선택합니다. M3의 TopAppBar는 배경에 surfaceColor를, 제목에 primary를 사용합니다. 다이나믹 컬러를 사용할 수 없는 경우 MaterialTheme의 폴백 팔레트가 적용됩니다. Google Material Design(2025)에 따르면 Android 12+ 사용자의 63%가 애플리케이션에서 다이나믹 컬러를 사용합니다.

MediumTopAppBar는 큰 제목(32 sp)이 있는 확장 변형으로, 스크롤 시 20 sp로 부드럽게 축소되어 SmallTopAppBar로 전환됩니다. 이 효과는 TopAppBarDefaults.mediumTopAppBarColors()와 scrollBehavior 매개변수를 통해 구현됩니다. 전환 애니메이션은 제목 축소를 추적하는 TopAppBarState를 통해 제어됩니다.

kotlin
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MediumTopBarExample() {
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    Scaffold(
        topBar = {
            MediumTopAppBar(
                title = { Text("Library") },
                navigationIcon = {
                    IconButton(onClick = { }) {
                        Icon(Icons.Filled.Menu, contentDescription = "Menu")
                    }
                },
                scrollBehavior = scrollBehavior
            )
        }
    ) { padding ->
        LazyColumn(contentPadding = padding) { /* content */ }
    }
}

Material3 TopAppBar를 사용하려면 @OptIn(ExperimentalMaterial3Api::class)를 사용해야 합니다. 이 어노테이션은 API가 향후 버전에서 변경될 수 있음을 나타냅니다. 2025년 현재 M3의 TopAppBar는 실험적이지만 Google은 적절한 테스트와 함께 프로덕션에서 사용할 것을 권장합니다.

ScrollBehavior: 스크롤 시 바 숨기기

ScrollBehavior는 콘텐츠를 세로로 스크롤하는 동안 TopAppBar의 가시성을 제어하는 메커니즘입니다. Jetpack Compose에서 scrollBehavior를 사용하면 공간을 확보하기 위해 바를 숨기거나 축소할 수 있으며, 이는 큰 콘텐츠 목록이 있는 화면에서 특히 유용합니다.

Material3는 세 가지 전략을 제공합니다: enterAlways(위로 스크롤하면 바가 나타나고 아래로 스크롤하면 숨겨짐), exitUntilCollapsed(제목이 완전히 축소된 후에만 바가 숨겨짐), TopAppBarScrollBehavior 인터페이스를 구현한 사용자 지정. 첫 번째 옵션은 콘텐츠 피드에 적합하고, 두 번째는 MediumTopAppBar가 있는 화면에 적합합니다.

ScrollBehavior는 rememberLazyListState()를 통해 LazyColumn 또는 LazyRow와의 조정이 필요합니다. 스크롤 상태는 scrollBehavior 매개변수를 통해 TopAppBar에 전달됩니다. 구성 요소는 스크롤 이벤트를 자동으로 구독하고 바 가시성을 애니메이션화합니다. Android Developers(2025)에 따르면 enterAlwaysScrollBehavior는 가장 인기 있는 전략으로, 스크롤 가능한 TopAppBar가 있는 애플리케이션의 75%에서 사용됩니다.

사용자 지정 ScrollBehavior 구성

사용자 지정 동작을 만들려면 TopAppBarScrollBehavior를 확장하고 onScroll 및 onDrag 메서드를 재정의합니다. 사용자 지정 동작은 표준 시나리오가 디자인 요구 사항을 충족하지 못할 때 유용합니다. 예를 들어, 특정 스크롤 임계값을 초과한 후에만 바를 숨겨야 하는 경우입니다.

기본적으로 scrollBehavior는 콘텐츠에 패딩을 추가하지 않습니다. paddingTop은 Scaffold의 contentPadding을 통해 또는 LazyColumn의 Modifier.padding을 통해 수동으로 설정해야 합니다. MediumTopAppBar에서는 여백이 TopAppBarState.collapsedFraction을 통해 자동으로 계산됩니다.

kotlin
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
    topBar = {
        MediumTopAppBar(
            title = { Text("Content") },
            scrollBehavior = scrollBehavior
        )
    }
) { padding ->
    LazyColumn(contentPadding = padding) { /* items */ }
}

ScrollBehavior는 Material3에서만 사용할 수 있습니다. Material2 TopAppBar에는 스크롤 시 숨기기에 대한 기본 제공 지원이 없으며, 유사한 동작을 위해서는 NestedScrollConnection을 통한 수동 구현이 필요합니다.

자주 묻는 질문

Android에서 TopAppBar와 Toolbar의 차이점은 무엇인가요?

TopAppBar는 App Bar의 Compose 구현으로, 컴포저블 함수를 통해 선언적으로 작동합니다. Toolbar는 XML 레이아웃의 View 구성 요소입니다. TopAppBar는 Compose 테마에 자동으로 적응하고, 슬롯 API를 지원하며, Activity 코드를 통해 관리되는 Toolbar와 달리 findViewById가 필요하지 않습니다.

TopAppBar의 그림자를 제거하려면 어떻게 해야 하나요?

Material3에서는 그림자가 기본적으로 없습니다. TopAppBar는 elevation 대신 표면 색상을 사용합니다. Material2에서는 elevation = 0.dp 매개변수를 설정하여 그림자를 제거합니다. 추가로 완전히 제거하려면 Modifier.shadow(0.dp)를 호출할 수 있습니다.

TopAppBar에 검색창을 추가하려면 어떻게 해야 하나요?

TextField가 포함된 컴포저블 블록을 title 매개변수에 전달합니다. 검색이 활성화되면 조건부 렌더링을 통해 navigationIcon과 actions를 숨깁니다. 상태는 remember를 통해 저장합니다: var isSearching by remember { mutableStateOf(false) }. isSearching = true이면 Text 대신 title에 TextField를 렌더링합니다.

TopAppBar는 두 줄 제목을 지원하나요?

네, title 매개변수의 사용자 지정 컴포저블을 통해 지원합니다. 단일 Text 대신 두 개의 Text 요소가 있는 Column을 전달합니다. 첫 번째는 기본 제목(semibold), 두 번째는 부제목(medium, 더 작은 크기)입니다. MediumTopAppBar에는 축소 애니메이션이 있는 두 줄 제목에 대한 기본 제공 지원이 있습니다.

TopAppBar가 상태 표시줄과 겹치는 이유는 무엇인가요?

TopAppBar는 시스템 여백을 자동으로 고려하지 않습니다. TopAppBar에 Modifier.statusBarsPadding()을 적용하거나 WindowInsets을 처리하는 Scaffold를 사용해야 합니다. Material3에서는 시스템 바 여백을 자동으로 처리하기 위해 windowInsets 매개변수가 추가되었습니다.

요약

  • TopAppBar는 Jetpack Compose의 주요 상단 바 구성 요소로, title, navigationIcon 및 actions와 함께 슬롯 API를 통해 구현됩니다
  • Material3는 다이나믹 컬러 지원과 함께 세 가지 변형(SmallTopAppBar, CenterAlignedTopAppBar, MediumTopAppBar)을 제공합니다
  • NavigationIcon은 Drawer를 열거나 돌아가는 데 사용되며, actions는 상황별 아이콘에 사용됩니다
  • ScrollBehavior는 enterAlways 및 exitUntilCollapsed 전략을 통해 스크롤 시 TopAppBar의 가시성을 제어합니다
  • DropdownMenu를 사용하면 MoreVert 아이콘이 있는 드롭다운 메뉴에 오버플로 액션을 배치할 수 있습니다
  • 다이나믹 컬러는 Android 12+에서 TopAppBar 색상을 기기 배경화면에 자동으로 적응시킵니다
  • 상태 표시줄과의 겹침을 방지하려면 Modifier.statusBarsPadding() 또는 M3의 windowInsets 매개변수를 사용합니다

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기