티스토리 뷰
💡 넥스트 스탭의 TDD, 클린 코드 with Kotlin 8기 강의를 수강하며 정리한 내용입니다.
목차
Wrapping Class
객체 지향 설계를 따르다보면, 때로는 도메인별 특정 유형을 만들기 위해 값을 클래스로 래핑하는 것이 유용하다. 예를 들어 영화 제목과 티켓 가격을 나타내는 Movie 클래스를 가정해보자.
class Movie(
val name: String,
val ticketPrice: Long,
)
이 때 도메인에 특화된 설계를 위해서 영화 표 가격 타이블 Long으로 두는 것 대신 이를 래핑(Wrapping)하는 Price 클래스를 둘 수 있다.
class Movie(
val name: String,
val ticketPrice: Price,
)
class Price(
val price: Long,
)
이를 통해 도메인에 특화된 타입을 선언하여 타입을 명확히 나타내고 안정성을 확보할 수 있다.
하지만
이는 추가적인 Heap 할당으로 인한 런타임 오버헤드를 유발한다. 또한 더욱이 래핑된 타입이 원시 타입(Int, Long 등) 인 경우, 성능 저하는 심각해진다. 왜냐하면 원시 타입은 보통 런타임 시점에 컴파일러에 의해 매우 최적화되는 반면, 래퍼 클래스는 특별한 처리를 받지 못하기 때문이다.
Inline Class
이러한 문제를 해결하기 위해 Kotlin은 인라인 클래스(Inline Class)라는 특별한 종류의 클래스를 제공한다.
인라인 클래스는 JVM 상에서 원시 타입과 같은 성능을 제공하면서도 타입 안전성을 유지할 수 있는 Kotlin의 기능이다. 인라인 클래스는 값 기반 클래스의 부분 집합으로, 오직 값만을 보유할 수 있다. 예를 들어 위 Price 클래스는 다음과 같이 인라인 클래스로 선언할 수 있다.
value class Price(
val price: Long,
)
JVM 상에서 인라인 클래스의 특징(타입 안전성과 성능 이슈)을 제대로 활용하기 위해 value 키워드는 @JvmInline 어노테이션과 함께 사용해야한다.
@JvmInline
value class Price(
val price: Long,
)
위 코드를 자바 코드로 디컴파일하면 다음과 같은 Price 클래스를 볼 수 있다.
public final class Price {
private final long price;
public final long getPrice() {
return this.price;
}
...
}
사용 예시
인라인 클래스는 인스턴스화시, 기본 생성자로 초기화되는 원시 타입의 단일 속성(= 원본 타입)을 반드시 가져야한다. 인라인 클래스의 초기 값은 반드시 기본 생성자로 설정되어야하며, 상속할 수 없다.
class PriceTest {
@Test
fun test() {
val ticketPrice = Price(price = 13_000)
}
}
위 테스트 코드를 자바 코드로 디컴파일한 결과는 다음과 같다.
public final class PriceTest {
@Test
public final void test() {
// constructor-impl : Kotlin 컴파일러가 생성한 최적화된 내부 메서드
long ticketPrice = Price.constructor-impl(13000L);
}
}
코틀린 컴파일러에 의해 Price자리에 객체 인스턴스 대신 원시 타입 long이 들어온 것을 볼 수 있다.
정리
코틀린의 인라인 클래스를 사용하면 추가적인 객체 생성 없이 원본 값이 직접 사용되며, 성능 오버헤드 없이 타입 안전성을 확보할 수 있다. 인라인 클래스의 인스턴스는 런타임 시점에 원본 타입으로 완전히 대체된다. 즉, 클래스의 데이터가 런타입시 사용 지점에서 원본 타입으로 인라인된다.
출처
'Java & Kotlin' 카테고리의 다른 글
[Kotlin] check()와 require(), 코틀린 람다 표현식 {} (0) | 2024.12.01 |
---|---|
[JVM] JVM 기반언어, 자바와 코틀린의 빌드 과정과 실행 원리 (1) | 2024.11.24 |
[Java] 자바의 두가지 정렬 방법(Comparable, Comparator) (0) | 2024.08.01 |
[Java] 주요 함수형 인터페이스(Function Interface) (2/2) (0) | 2024.03.19 |
[Java] 함수형 프로그래밍(Functional Programming)과 람다식(Lambda Expression) (1/2) (0) | 2024.03.10 |