프로그래밍백엔드 개발자

인라인 리피피드 파라미터(reified generics)란 무엇이며, Kotlin에서 언제, 왜 사용하는지, 어떤 제한 사항이 있는지 및 그 사용 예시는 무엇인지요?

Hintsage AI 어시스턴트로 면접 통과

답변.

문제의 역사:

JVM에서는 실행 중에 제네릭 매개변수에 대한 정보가 없는 경우가 있습니다(타입 소거). Kotlin은 인라인 함수에 대한 리피피드 제네릭 매개변수 메커니즘을 제안하여 T 타입에 대한 정보를 실행 중에 쿼리할 수 있도록 하였습니다. 이는 Kotlin 언어의 가장 강력한 도구 중 하나입니다.

문제:

T 타입(제네릭)을 받아들이는 함수를 작성해야 하며, 매개변수의 타입에 따라 서로 다른 작업을 수행해야 합니다. java.lang.Class를 명시적으로 전달하거나 Java의 리플렉션을 사용하지 않고, 클라시컬 타입 소거는 실행 시 T 타입을 알 수 없습니다.

해결책:

Kotlin에서는 인라인 함수에 리피피드 수식어를 붙여 제네릭 매개변수를 선언할 수 있으며, 이를 통해 함수 본체 내부에서 T 타입을 "구체화"하여 일반 타입처럼 사용하고 타입 체크 및 리플렉션을 통해 인스턴스를 생성할 수 있습니다.

코드 예시:

inline fun <reified T> isOfType(value: Any): Boolean { return value is T } isOfType<String>(123) // false isOfType<Int>(123) // true

주요 특징:

  • 실행 시 함수 내부에서 T 타입에 접근 가능
  • value is T, T::class, T::class.java와 같은 타입 연산 호출 가능
  • 인라인 함수에서만 작동

함정 질문.

리피피드를 인라인 함수 외부에서 사용할 수 있습니까?

아니요! 오직 인라인 함수(및 인라인 지연 속성)만 리피피드 제네릭 매개변수를 가질 수 있습니다. 그 이유는 호출 위치에서의 코드 치환이 필요하며, 이를 통해 T 대신 구체적 타입을 "치환"할 수 있기 때문입니다.

코드 예시:

// 컴파일 오류: fun <reified T> errorFun() { } // 올바른 예: inline fun <reified T> okFun() { }

인라인 리피피드 함수 내에서 Class<T>를 얻을 수 있습니까?

네! T::class.java 또는 T::class를 작성하기만 하면 됩니다. 이는 제네릭 팩토리, 파서 및 리플렉션 API 작업을 작성하는 데 매우 유용합니다.

코드 예시:

inline fun <reified T> printType() { println(T::class.java) } printType<String>() // class java.lang.String

리피피드 함수 내에서 T 타입을 생성자로 인스턴스화 할 수 있습니까?

부분적으로 가능합니다. 리플렉션을 사용할 수 있지만, C++나 C#처럼 new T()를 직접 사용할 수는 없습니다:

inline fun <reified T : Any> makeInstance(): T? { return T::class.constructors.firstOrNull()?.call() }

하지만 이 방법은 T에 기본 생성자가 있어야 합니다.

일반적인 오류 및 안티 패턴

  • 리피피드를 지나치게 자주 재사용하여 타입을 명시적으로 전달해야 하는 곳(예: 단순히 Class<T>가 필요한 곳)에서 사용
  • 인라인 함수가 아닌 경우 리피피드 사용
  • 적절한 생성자를 제공하지 않고 T를 항상 인스턴스화 할 수 있다고 기대

실제 사례

부정적인 사례

리피피드를 포함하여 코드에서 무거운 리플렉션 작업을 호출하는 함수:

inline fun <reified T> foo(): T? = T::class.constructors.firstOrNull()?.call()

장점:

  • 일반적이고 테스트에 편리함

단점:

  • 느림
  • 생성자 오류에 대한 제어가 없음, 디버그하기 어려움

긍정적인 사례

일반 유형 체크 또는 안전한 캐스트를 위해 리피피드를 사용하는 경우:

inline fun <reified T> safeCast(value: Any?): T? = value as? T

장점:

  • 간결함
  • 안전함 (as?)
  • 성능 오버헤드 없음

단점:

  • 인라인 함수에서만 지원됨