Developing Myself Everyday
article thumbnail

사진: UnsplashTahlia Doyle

 

 

List에 대해서 배울 때, 우리는 일반적으로 MutableList와 비교하며 List는 변경될 수 없는 Immutable한 컬렉션이라고 배웠습니다.

 

다만, 이는 큰 관점에서는 틀린 정보입니다. 그래서 이번 게시글에서는 List가 왜 Immutable하지 않는지, 그리고 Immutable한 컬렉션은 뭐가 있는지 알아보고자 합니다.


 

 

 

List는 Immutable하지 않다!


List는 Read-only라고 말합니다. 변경할 수 없고, 오직 읽을 수만 있는 컬렉션이라고 우리는 배워왔습니다.

 

다만, 이는 넓은 관점에서는 틀린 말입니다.

 

아래의 코드를 보겠습니다. 변수 `number`는 val로 선언되어 있기 때문에 변경될 수 없습니다.

class Example {
    val number = 12
}

 

 

코틀린에서 이러한 변수들은 프로퍼티라고 부릅니다. 코틀린에서는 자바의 필드를 코드 내부에 캡슐화하여 프로퍼티를 통한 간접적인 접근을 가능하게 합니다.

public final class Example {
   private final int number = 12;

   public final int getNumber() {
      return this.number;
   }
}

 

 

자바의 관점에서 필드가 final로 선언되었다면, 이는 어떠한 상황에서 변하지 않는 값이 됩니다.

 

이제 리스트를 한번 보겠습니다. 아래의 예시에서는 이전의 number를 리스트 안에 담고, 이를 val로 선언하여 불변으로 만들었습니다.

class Example {
    val number = 12
}

fun main() {
    val list = Arrays.asList(Example().number)
}

 

 

 

자바에서 Arrays.asList는 기본적으로 가변적입니다. 따라서, number의 값이 변경될 수는 없지만 리스트가 참조하고 있는 값은 언제든지 재할당될 수 있습니다.

public static final void main() {
   List list = Arrays.asList((new Example()).getNumber());
}

 

 

이를 좀 더 쉽게 설명하기 위해 간단한 예시를 들어보겠습니다.

 

여기 가변으로 선언된 리스트와 불변으로 선언된 리스트가 있습니다.

fun main() {
    val mutableList = mutableListOf(1, 2)
    val list: List<Int> = mutableList
}

 

 

여기서 만약 가변 리스트를 변경시킨다면 어떻게 될까요??? 가변 리스트의 값만 바뀌고 이를 참조하고 있는 불변 리스트의 값은 바뀌지 않을까요???

 

정답은 불변 리스트의 값 또한 바뀐다는 것입니다.

fun main() {
    val mutableList = mutableListOf(1, 2)
    val list: List<Int> = mutableList

    mutableList.add(3)
    println(list) // [1, 2, 3]
}

 

 

하나의 예시를 더 들어보겠습니다. 불변 리스트를 정의한 다음, 다른 변수에 불변 리스트를 캐스하고, 가변 리스트로 할당해 보겠습니다.

 

이러한 경우에도 기존 불변 리스트의 값은 변하게 됩니다.

fun main() {
    val list: List<Int> = listOf(1, 2)
    val mutableList = list as MutableList<Int>

    mutableList[0] = 100
    println(list) // [100, 2]
}

 

 

 

 

Immutable한 컬렉션을 만드는 방법


어떠한 상황에서 변하지 않는 Immutable한 컬렉션을 만드는 방법은 다양합니다. 다만 여기서는 Kotlin에서 Immutable 컬렉션을 만들 수 있는 방법인 Immutable Collection과 추가로 Persistent Collection을 지원하는 라이브러리에 대해 알아보고자 합니다.

 

 

GitHub - Kotlin/kotlinx.collections.immutable: Immutable persistent collections for Kotlin

Immutable persistent collections for Kotlin. Contribute to Kotlin/kotlinx.collections.immutable development by creating an account on GitHub.

github.com

 

 

Immutable Collection은 간단합니다. 확장 함수로 Immutable로 변경해주기만 하면 해당 컬렉션은 이제 어떠한 방식으로도 변경할 수 없는 컬렉션이 됩니다.

fun main() {
    val mutableList = mutableListOf(1, 2)
    val list: List<Int> = mutableList.toImmutableList()

    mutableList.add(3)
    println(list) // [1, 2]
}

 

 

Persistent Collection은 기본 데이터 구조의 포인터를 업데이트 해서 컬렉션의 변경 사항을 반영하는 방식으로만 수정할 수 있는 컬렉션입니다.

 

Immutable Collection을 기반으로 하여 수정 작업이 가능하게 만든 컬렉션이라 생각하면 될 것 같습니다.

 

Persistent Collection은 변경 내용이 있을 경우, 이를 반영하는 새로운 컬렉션을 생성하는 방식으로 수정 작업을 처리합니다.

 

 

 

 

Compose에서 이러한 컬렉션을 사용해야 하는 이유


Compose의 Reposition은 컴포저블의 매개변수 상태가 변할 때 일어나게 됩니다. 

 

만약 매개변수의 타입이 불안정하거나 변경될 수 있다면, 해당 컴포저블에 Reposition이 일어나게 됩니다.,

 

만약 해당 컴포저블에 Reposition을 발생시키지 않고자 하려면, 해당 매개변수를 Stable하게 유지해서 컴포저블이 Reposition되지 않게 해야할 것입니다.

 

그렇기 때문에 Reposition을 발생시키지 않기 위해서 우리는 매개변수가 될 수 있는 컬렉션을 Immutable Collection으로 사용하는 것이 좋습니다.

 

 

 

 

 

Reference


 

Kotlin Lists are Read-only and not Immutable except when there is only 1 element

I’d always assumed thatList in Kotlin is immutable, but while writing another post, I learnt that it is technically read-only and not…

medium.com

 

 

Java Immutability Visualised

In Java, mutability is the default; we are always able to reassign variables to point to something else. Mutability is not always ideal…

medium.com

 

profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!