연락처 목록, SNS 피드, 상품 리스트, 설정 화면까지... 앱을 만들다 보면 '목록'을 표시해야 하는 경우는 셀 수 없이 많습니다.
Compose를 처음 배울 때 Column 안에 for문을 돌려 UI를 추가하는 방법을 떠올릴 수 있습니다. 하지만 아이템이 10개, 20개를 넘어 100개, 1000개가 된다면 어떻게 될까요? 앱은 심하게 버벅이다가 결국 비정상 종료될지도 모릅니다.
이번에는 Compose에서 목록을 효과적으로 보여주기 위한 방법에 대해 알아보겠습니다.
왜 Column이 아닌 LazyColumn?
이 둘의 차이를 이해하는 것이 가장 중요합니다.
- Column: Column 안에 있는 모든 자식 Composable을 한 번에 메모리에 올리고 화면에 그립니다. 1000개의 아이템이 있다면 1000개 전부를 렌더링하려고 시도하죠. 이는 엄청난 메모리 낭비와 성능 저하를 일으킵니다.
- LazyColumn: 이름의 'Lazy(게으른)'에서 알 수 있듯, 지금 당장 화면에 보이는 아이템만 렌더링합니다. 사용자가 스크롤을 내리면, 화면 밖으로 사라지는 아이템은 메모리에서 재활용하고 새로 나타날 아이템만 그립니다. 이는 RecyclerView의 동작 원리와 같습니다.
Column은 1000페이지짜리 책을 한 번에 모두 인쇄하는 것과 같고, LazyColumn은 웹 브라우저가 화면에 보이는 부분만 로딩하는 것과 같습니다. 당연히 후자가 훨씬 효율적이죠!
LazyColumn 기본 사용법
LazyColumn의 사용법은 매우 직관적입니다. LazyColumn의 컨텐츠 블록 안에서 items라는 특별한 함수를 사용합니다.
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun SimpleList() {
LazyColumn {
// 100개의 아이템을 가진 리스트
items(100) { index ->
Text(text = "아이템 #$index")
}
}
}
조금 더 복잡한 예제를 살펴 보겠습니다.
// 1. 데이터 클래스 정의
data class User(val id: Int, val name: String)
// 2. 아이템 하나의 UI를 담당할 Composable
@Composable
fun UserCard(user: User) {
Row(modifier = Modifier.padding(16.dp)) {
Image(
painter = painterResource(id = R.drawable.ic_profile),
contentDescription = "Profile Picture"
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = user.name)
}
}
// 3. LazyColumn과 연결
@Composable
fun UserList(users: List<User>) {
LazyColumn {
items(items = users) { user ->
UserCard(user = user)
}
}
}
실제 앱에서는 보통 데이터 클래스의 리스트를 다루게 됩니다. 각 아이템의 UI를 별도의 Composable 함수로 분리하는 것이 좋은 습관입니다.
성능 최적화 하기
LazyColumn에서는 Compose의 성능 최적화를 위해서 key를 제공하고 있습니다. 이 key를 이용한다면 더욱 더 매끄러운 앱을 만들 수 있습니다.
items(
items = users,
// 각 아이템에 고유하고 안정적인 키를 제공합니다.
key = { user -> user.id }
) { user ->
UserCard(user = user)
}
key를 왜 사용해야 할까요?
리스트의 데이터가 변경(추가, 삭제, 순서 변경)될 때, Compose는 어떤 아이템이 어떤 것인지 구별해야 합니다.
- key가 없으면: Compose는 아이템의 위치를 기준으로 판단합니다. 리스트 맨 앞에 아이템이 추가되면, Compose는 모든 아이템이 한 칸씩 밀렸다고 생각하고 전부 다시 그리는 비효율적인 작업을 할 수 있습니다.
- key가 있으면: Compose는 user.id와 같은 고유한 key를 보고 아이템을 식별합니다. 리스트가 바뀌어도 "아, id가 5인 아이템은 그대로 있구나. 다시 그릴 필요 없겠네."라고 판단하여 꼭 필요한 부분만 업데이트합니다.
key 사용의 장점:
- 성능 향상: 불필요한 재구성(Recomposition)을 방지합니다.
- 상태 유지: 아이템이 가진 내부 상태(remember로 관리되는)가 유지됩니다.
- 애니메이션 최적화: 아이템 추가/삭제 시 애니메이션이 더 자연스러워집니다.
LazyColumn의 items에는 항상 고유하고 안정적인 key를 제공하는 습관을 들이세요. 보통 데이터의 id를 사용합니다.
블로그 글에 대해 궁금한 점이 있다면 아래 카카오톡 오픈채팅에 들어와서 질문해주세요
Android Kotlin Compose QnA
open.kakao.com
'개발 > Compose' 카테고리의 다른 글
(Compose) Stateful vs Stateless (4) | 2025.08.07 |
---|---|
(Compose) Compose UI Test (4) | 2025.08.05 |
(Compose) Modifier (2) | 2025.08.04 |
(Compose) 상태(state) (2) | 2025.08.04 |
(Compose) @Preview (2) | 2025.08.04 |