본문 바로가기
Kotlin

[깡샘의 코틀린 프로그래밍] 정리 18 - 리플렉션

by 들풀민들레 2018. 3. 2.

본 글은 [깡샘의 코틀린 프로그래밍 - 루비페이퍼] 의 내용을 발췌한 것입니다.

좀더 자세한 내용은 책을 통해 확인해 주세요.

 

 

 

18장. 리플렉션과 어노테이션

 

18.1.1. 리플렉션 이해

 

리플렉션이란?

 

리플렉션(Reflection)은 사전적 의미로 투영, 반사라는 뜻입니다. 프로그램에서 리플렉션은 런타임 때 프로그램의 구조(객체, 함수, 프로퍼티)를 분석해 내는 기법을 이야기합니다. 예를 들어 어떤 함수를 정의하는데 함수의 매개변수로 클래스 타입을 선언하고 런타임 때 매개변수로 전달된 클래스의 이름, 클래스의 함수나 프로퍼티를 동적으로 판단하는 작업을 리플렉션이라고 합니다.

 

코틀린에서 리플렉션을 위해서는 라이브러리가 필요합니다. kotlin-reflect.jar라는 라이브러리를 의존성(dependency) 설정을 통해 준비해야 합니다. 사용하는 빌드 시스템이 그레들이라면 그레들 환경 파일(build.gradle)에 다음처럼 라이브러리를 등록합니다.

 

01 //…

02 dependencies {

03 compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"

04 testCompile group: 'junit', name: 'junit', version: '4.12'

05 compile "org.jetbrains.kotlin:kotlin-reflect"

06 //…

07 }

08 //…

 

클래스 타입과 레퍼런스

 

런타임 때 동적으로 클래스를 분석하려면 클래스에 대한 정보가 필요한데 이 클래스에 대한 정보를 클래스 레퍼런스라고 표현하며, 클래스 레퍼런스를 대입받는 곳은 클래스 타입으로 선언해야 합니다. 즉, 클래스 타입으로 선언한 곳에 특정 클래스의 레퍼런스를 대입하면 런타임 때 클래스에 대한 다양한 정보를 분석할 수 있습니다.

클래스 타입은 KClass<*>로 표현하며 이곳에 대입하는 클래스 레퍼런스는 "클래스명::class"로 표현합니다.

 

01 package eighteen_one_one

02

03 import kotlin.reflect.KClass

04

05 val myVal: KClass<*> = String::class

06

07 fun myFun(arg: KClass<*>){

08

09 }

 

위 소스를 보면 05번 줄에 프로퍼티를 KClass<*> 타입으로 선언했습니다. 이 프로퍼티에는 클래스의 객체가 생성되어 대입되는 것이 아니라 클래스의 정보가 대입됩니다. 클래스의 정보는 클래스 레퍼런스라고 표현하며, String 클래스의 레퍼런스는 String::class로 표현합니다.

 

위 소스에서 클래스 타입을 KClass<*>로 작성했는데 이 타입에는 어떤 클래스 레퍼런스도 대입할 수 있습니다. 그런데 특정 클래스로 한정하려면 <*> 부분에 클래스명을 명시합니다. 예를 들어KClass<String>으로 명시하면 String 클래스의 레퍼런스만 등록할 수 있습니다. 또한, 클래스 레퍼런스는 코틀린 클래스와 자바 클래스가 다른데 코틀린 클래스는 "클래스명::class"로 표현하며 자바 클래스는 "클래스명::class.java"로 표현합니다.

 

01 package eighteen_one_one_one

02

03 import kotlin.reflect.KClass

04

05 val myVal: KClass<String> = String::class

06

07 val myVal2: KClass<String> = Double::class //에러

08

09 val myVal3: Class<*> = String::class.java

 

위 소스의 05번 줄에 클래스 타입을 KClass<String>으로 선언했습니다. <String>을 명시했으므로 이곳에는 String 클래스의 레퍼런스만 대입할 수 있으며 다른 클래스의 레퍼런스를 대입하면 에러가 발생합니다. 또한, 자바 클래스의 레퍼런스는 09번 줄처럼 뒤에 .java를 추가하여 String::class.java로 명시해야 하며, 이를 받으려면 클래스 타입을 Class<*>로 선언해야 합니다.