반응형
모바일 앱에서 무한 스크롤은 필수적인 UI 패턴 중 하나입니다. Jetpack의 Paging 3 라이브러리와 Jetpack Compose를 결합하면 복잡한 리스트 페이징을 간단하게 구현할 수 있습니다. 이번 글에서는 Compose와 Paging 3를 활용해 무한 스크롤 리스트를 구현하는 방법을 살펴보겠습니다.
1. Paging 3 기본 구조
- PagingSource: 데이터 페이지를 로드하는 클래스
- Pager: PagingSource를 사용해 Flow를 생성
- PagingData: UI로 전달되는 페이징 데이터 컨테이너
2. PagingSource 구현
class UserPagingSource(
private val api: ApiService
) : PagingSource<Int, User>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, User> {
return try {
val page = params.key ?: 1
val response = api.getUsers(page)
LoadResult.Page(
data = response.users,
prevKey = if (page == 1) null else page - 1,
nextKey = if (response.users.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, User>): Int? {
return state.anchorPosition?.let { anchorPosition ->
state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1)
?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
}
}
}
3. Pager 설정 (Repository)
class UserRepository(private val api: ApiService) {
fun getUserPagingData(): Flow<PagingData<User>> {
return Pager(
config = PagingConfig(pageSize = 20, enablePlaceholders = false),
pagingSourceFactory = { UserPagingSource(api) }
).flow
}
}
4. ViewModel에서 Flow 전달
class UserViewModel(private val repository: UserRepository) : ViewModel() {
val users = repository.getUserPagingData()
.cachedIn(viewModelScope)
}
5. Compose UI에서 PagingData 구독
Compose에서는 collectAsLazyPagingItems()를 통해 PagingData를 바로 리스트에 연결할 수 있습니다.
@Composable
fun UserListScreen(viewModel: UserViewModel) {
val users = viewModel.users.collectAsLazyPagingItems()
LazyColumn {
items(users.itemCount) { index ->
val user = users[index]
if (user != null) {
Text(user.name)
} else {
CircularProgressIndicator() // 로딩 표시
}
}
users.apply {
when {
loadState.refresh is LoadState.Error -> {
item { Text("새로고침 실패") }
}
loadState.append is LoadState.Error -> {
item { Text("더 불러오기 실패") }
}
}
}
}
}
6. 무한 스크롤 UX 팁
- 마지막 아이템 아래 로딩 인디케이터 추가
- 에러 발생 시 재시도 버튼 제공
- Pull-to-refresh(스와이프 새로고침)과 함께 사용하면 UX 향상
7. 결론
Compose와 Paging 3를 함께 사용하면 무한 스크롤 구현이 매우 간단해집니다. 기존 RecyclerView + Adapter 대비 코드가 훨씬 줄어들고, 상태 관리도 Flow로 통합할 수 있습니다.
다음 글 예고: 다음 글에서는 멀티 모듈 + Clean Architecture 구조로 Compose 앱 설계하기를 다뤄보겠습니다.
반응형
'개발일기' 카테고리의 다른 글
| OkHttp Interceptor로 공통 로깅 및 에러 처리하기 (1) | 2025.09.22 |
|---|---|
| 멀티 모듈 + Clean Architecture로 Compose 앱 설계하기 (4) | 2025.09.19 |
| 안드로이드 네트워크 + 로컬 캐싱 전략 (Room + Flow) (1) | 2025.09.11 |
| 안드로이드 에러 처리 및 UI 피드백 전략 (2) | 2025.09.10 |
| Jetpack Compose와 네트워크 계층 연결하기 (2) | 2025.09.09 |