
Kotlin의 kotlinx.collections.immutable는 불변 컬렉션을 효율적으로 다루기 위한 전용 컬렉션 구현체를 제공합니다. 특히 ImmutableList와 PersistentList는 API 설계와 내부 구현에서 각각 다른 목적을 갖습니다.
// PersistentList로 생성하고
val list = persistentListOf(1, 2, 3)
// ImmutableList 타입으로 노출
fun getItems(): ImmutableList<Int> = list
Kotlin Collection
↓
List<E>
↓
ImmutableList<E> ← 읽기 전용 계약
↓
PersistentList<E> ← 불변성을 유지하며 수정 가능
↓
PersistentVector<E> ← 실제 구현체 (internal)
public interface ImmutableList<out E> : List<E>, ImmutableCollection<E>add(), removeAt(), set() 등의 메서드 제공 public interface PersistentList<out E> : ImmutableList<E> {
fun add(element: @UnsafeVariance E): PersistentList<E>
fun add(index: Int, element: @UnsafeVariance E): PersistentList<E>
fun removeAt(index: Int): PersistentList<E>
fun set(index: Int, element: @UnsafeVariance E): PersistentList<E>
// ...
}
일반적인 불변 컬렉션과의 차이점
// 일반 불변 리스트 (매번 전체 복사)
val list1 = listOf(1, 2, 3, 4, 5) // O(n) 메모리
val list2 = list1 + 6 // O(n) 복사
val list3 = list2 + 7 // O(n) 복사
// 매번 전체 리스트를 복사하므로 비효율적
// Persistent 리스트 (구조적 공유)
var plist = persistentListOf(1, 2, 3, 4, 5) // O(n) 메모리
plist = plist.add(6) // O(log n) - 변경된 부분만 새로 생성
plist = plist.add(7) // O(log n) - 대부분의 구조 공유
// 이전 버전들과 대부분의 내부 구조를 공유하여 효율적
Persistent Data Structure는 내부적으로 트리 구조를 사용합니다.
| 상황 | 권장 타입 |
|---|---|
| 외부에 상태 노출 (ViewModel, Domain, API) | ImmutableList |
| 내부에서 변형 가능한 불변 컬렉션 필요 | PersistentList |
| 매번 전체 복사 비용을 피하고 싶을 때 | PersistentList |