소개


우리는 코드를 쓸 때 하나의 value 값만을 가지고 있는 클래스를 좀 더 도메인을 다루듯 사용하고 싶어 클래스로 래핑하고 싶은 경우가 있다. 하지만 이러한 방식은 heap allocation 으로 인해 런타임 오버헤드가 생길 수 있다. 특히 primitive 타입은 최적화가 잘 되어있기 때문에 이를 래핑하는 클래스를 만드는 것은 더욱 큰 오버헤드를 가져올 수 있다.

이러한 문제를 해결하기 위해서 코틀린은 inline class 라는 것을 제공한다.

@JvmInline
value class Password(private val s: String)

성능 최적화

인라인 클래스는 항상 하나의 프로퍼티만 가지고 있어야하며, 주생성자로 초기화되어야 한다. 런타임에는 이 인스턴스가 single property로 동작한다. 이게 어떤 말이냐면..

val password = Password("jahni123")

위와 같은 코드를 쓰게되면 런타임에는 Password 클래스가 인스턴스화 되는 것이 아니고 jahni123 이라는 단순 스트링으로 처리된다.

타입 안정성

이러한 value class를 사용하면 같은 데이터 타입을 사용하는 여러 값들 사이에서 혼동을 방지할 수 있다. 예를 들어 다음과 같이 쓸 수 있다.

@JvmInline
value class UserId(val id: String)

@JvmInline
value class ProductId(val id: String)

fun findUser(userId: UserId) { /*...*/ }
fun findProduct(productId: ProductId) { /*...*/ }

findUser(UserId("123")) // OK
findProduct(ProductId("123")) // OK
// findUser(ProductId("123")) // ERROR: 타입이 다름 

불변성

value class는 내부적으로 항상 불변이다. 불변이 주는 장점을 다 취할 수 있는 것이다.

@JvmInline
value class Age(val value: Int)

val age = Age(25)
// age.value = 30 // 컴파일 오류: 값을 변경할 수 없음