Compose 목록에서 페이징
LazyColumn으로 페이지 단위 데이터를 렌더링합니다.
Compose 목록에서 페이징은(는) CoddyKit의 무료 Android Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Android Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
Compose에서 페이지 데이터 렌더링하기
데이터 계층은 Flow<PagingData<Article>>를 제공합니다. paging-compose 라이브러리는 이 흐름을 LazyColumn이 렌더링할 수 있는 형태로 변환하며, 사용자가 스크롤할 때 필요에 따라 로드하는 기능도 제공합니다.
이를 연결하는 핵심은 collectAsLazyPagingItems()입니다.
collectAsLazyPagingItems
컴포저블 내부에서 흐름에 collectAsLazyPagingItems()를 호출합니다. 그러면 로드된 항목과 로드 상태를 추적하고, 페이지가 도착할 때 UI를 다시 구성하는 LazyPagingItems 객체가 반환됩니다.
import androidx.paging.compose.collectAsLazyPagingItems
@Composable
fun ArticleScreen(viewModel: ArticleViewModel) {
val articles = viewModel.articles.collectAsLazyPagingItems()
ArticleList(articles)
}LazyPagingItems와 함께 items() 사용하기
LazyColumn 내부에서 Paging의 items() 오버로드를 사용합니다. 이 함수는 LazyPagingItems에서 데이터를 읽고 사용자가 끝에 가까워지면 다음 페이지 로드를 시작합니다.
자리 표시자가 활성화되어 있으면 각 항목이 null일 수 있으므로 이 경우를 처리해야 합니다.
import androidx.compose.foundation.lazy.LazyColumn
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.items
@Composable
fun ArticleList(articles: LazyPagingItems<Article>) {
LazyColumn {
items(articles) { article ->
if (article != null) {
ArticleRow(article)
}
}
}
}항목에 안정적인 키 사용하기
각 행에 안정적인 키를 지정하면 Compose가 페이지 로드 사이에서 항목을 효율적으로 추적하고 불필요한 재구성을 방지할 수 있습니다.
항목 ID처럼 고유하고 안정적인 속성과 함께 Paging의 itemKey 도우미를 사용하세요.
import androidx.paging.compose.itemKey
LazyColumn {
items(
count = articles.itemCount,
key = articles.itemKey { it.id }
) { index ->
val article = articles[index]
if (article != null) ArticleRow(article)
}
}로드 상태 읽기
LazyPagingItems.loadState는 다음 세 가지 작업의 현재 로딩 및 오류 상태를 노출합니다.
refresh- 초기 로드 또는 당겨서 새로 고침 로드append- 다음 페이지 로드(아래로 스크롤)prepend- 이전 페이지 로드(위로 스크롤)
import androidx.paging.LoadState
val refresh = articles.loadState.refresh
val append = articles.loadState.append
val isInitialLoading = refresh is LoadState.Loading
val isLoadingMore = append is LoadState.Loading전체 화면 로딩 및 빈 상태
refresh 상태를 사용해 첫 화면을 제어하세요. 로딩 중에는 가운데에 로딩 표시기를 표시하고, 실패하면 오류 화면을 표시하며, 표시할 내용이 없으면 빈 상태 메시지를 표시합니다.
when (val refresh = articles.loadState.refresh) {
is LoadState.Loading -> FullScreenSpinner()
is LoadState.Error -> FullScreenError(
message = refresh.error.message,
onRetry = { articles.retry() }
)
is LoadState.NotLoading -> {
if (articles.itemCount == 0) EmptyState()
else ArticleList(articles)
}
}추가 로드 중 하단 로딩 표시기
다음 페이지를 로드하는 동안 하단에 작은 로딩 표시기를 표시하려면 append 로드 상태에 따라 LazyColumn에 항목을 하나 더 추가합니다.
LazyColumn {
items(count = articles.itemCount, key = articles.itemKey { it.id }) { index ->
articles[index]?.let { ArticleRow(it) }
}
if (articles.loadState.append is LoadState.Loading) {
item {
Box(Modifier.fillMaxWidth().padding(16.dp), Alignment.Center) {
CircularProgressIndicator()
}
}
}
}오류 발생 시 재시도
추가 로드가 실패하면 하단에 재시도 행을 표시합니다. articles.retry()를 호출하면 실패한 로드만 다시 시도하며 전체 목록을 다시 로드하지는 않습니다.
val append = articles.loadState.append
if (append is LoadState.Error) {
item {
Row(Modifier.fillMaxWidth().padding(16.dp), Arrangement.Center) {
Text("Couldn't load more")
Spacer(Modifier.width(8.dp))
Button(onClick = { articles.retry() }) { Text("Retry") }
}
}
}당겨서 새로 고침
articles.refresh()로 새 로드를 시작합니다. 이를 Material 3의 당겨서 새로 고침 기능과 결합하고, refresh 로드 상태에 따라 표시기를 제어하세요.
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
val isRefreshing = articles.loadState.refresh is LoadState.Loading
PullToRefreshBox(
isRefreshing = isRefreshing,
onRefresh = { articles.refresh() }
) {
ArticleList(articles)
}헤더와 구분선
같은 LazyColumn에서 페이지 항목과 페이지와 무관한 콘텐츠를 자유롭게 함께 사용할 수 있습니다. 페이지 항목의 items() 호출 앞뒤에 고정 헤더, 검색창 또는 섹션 구분선을 추가하세요.
모든 콘텐츠가 하나의 LazyColumn에 있으므로 스크롤이 하나로 통합되어 부드럽게 유지됩니다.
LazyColumn {
item { SearchBar(query, onQueryChange) }
items(count = articles.itemCount, key = articles.itemKey { it.id }) { index ->
val article = articles[index]
if (article != null) {
ArticleRow(article)
HorizontalDivider()
}
}
if (articles.loadState.append.endOfPaginationReached) {
item { Text("You're all caught up", Modifier.padding(16.dp)) }
}
}페이지 목록 미리 보기
Compose 미리 보기와 테스트에는 실제 네트워크가 필요하지 않습니다. 샘플 데이터를 PagingData.from(...)으로 감싸 흐름으로 노출하면 됩니다.
이렇게 하면 목록 UI를 다른 요소와 분리하여 만들고 미리 볼 수 있습니다.
import androidx.paging.PagingData
import kotlinx.coroutines.flow.flowOf
@Preview
@Composable
fun ArticleListPreview() {
val sample = listOf(Article(1, "Hello"), Article(2, "World"))
val flow = flowOf(PagingData.from(sample))
ArticleList(flow.collectAsLazyPagingItems())
}빠른 확인
Flow<PagingData>를 Compose LazyColumn이 렌더링할 수 있는 형태로 변환하는 함수는 무엇인가요?
복습: Compose에서의 페이징
Jetpack Compose에서 페이지 데이터를 렌더링했습니다.
collectAsLazyPagingItems()가 흐름과 UI를 연결합니다.- Paging의
items()오버로드는 스크롤할 때 더 많은 데이터를 로드하며,null자리 표시자를 처리해야 합니다. - 안정적인 키에는
itemKey { it.id }를 사용합니다. loadState.refresh/append/prepend로 로딩 표시기, 오류 및 빈 상태를 제어합니다.retry()와refresh()로 오류를 복구하고 다시 로드합니다.
다음: RemoteMediator로 네트워크와 데이터베이스 결합하기.
자주 묻는 질문
“Compose 목록에서 페이징” 강의는 무료인가요?
네 — “Compose 목록에서 페이징” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Android Academy 강의 전체를 잠금 해제할 수 있습니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“Compose 목록에서 페이징”에서 뭘 배우나요?
LazyColumn으로 페이지 단위 데이터를 렌더링합니다. 브라우저에서 직접 실행하는 실습 코드로 Android Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Android Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Android Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“Compose 목록에서 페이징” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Android Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Android Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 페이징이 필요한 이유
- PagingSource와 Pager
- Compose 목록에서 페이징
- RemoteMediator와 캐싱