IMCAT.DEV
로그인 가입
Kotlin 중급 객체지향

Kotlin Kotlin의 Reflection 기초

Kotlin Kotlin의 Reflection 기초 — 중급

Kotlin의 Reflection 기초

1. 도입 (왜 배워야 하는가)

Kotlin의 Reflection은 런타임에 클래스와 객체의 정보를 탐색하고 조작할 수 있는 기능을 제공합니다. 이는 다양한 상황에서 유용하게 사용될 수 있습니다. 예를 들어, 동적으로 클래스의 속성을 읽거나 수정하고, 메소드를 호출할 수 있습니다. 실무에서는 의존성 주입, 프레임워크 설계, API 통신에서의 데이터 바인딩 등 다양한 곳에서 Reflection을 활용합니다.

만약 Reflection을 모른다면, 하드코딩된 방식으로만 데이터를 처리해야 하므로 유연성과 재사용성이 떨어지고 코드가 복잡해질 수 있습니다. 예를 들어, 다양한 타입의 객체를 처리하는 기능을 구현할 때, Reflection을 활용하면 코드의 가독성을 높이고 유지보수를 용이하게 할 수 있습니다.

2. 핵심 개념 설명

Reflection은 객체의 메타데이터를 조회하고 수정할 수 있는 능력을 의미합니다. 객체의 클래스 정보, 메소드, 속성 등을 런타임에 동적으로 접근할 수 있습니다. 이를 이해하기 쉽게 설명하자면, Reflection은 마치 건축가가 건물의 구조를 파악하기 위해 도면을 검사하는 것과 비슷합니다. 도면이 없으면 건물의 구조를 정확히 이해하기 어려운 것처럼, Reflection 없이는 객체의 구조를 명확하게 알기 어렵습니다.

용어정의
Class객체의 청사진으로, 객체가 어떤 속성과 메소드를 가질지를 정의합니다.
Property클래스에 포함된 속성으로, 객체의 상태를 표현합니다.
Method클래스에 정의된 함수로, 객체의 행동을 정의합니다.

3. 기본 코드 예제

Reflection의 기본적인 사용법을 보여주는 간단한 예제를 작성해 보겠습니다.

import kotlin.reflect.full.memberProperties

data class Person(val name: String, val age: Int)

fun main() {
    val person = Person("Alice", 30) // Person 객체 생성
    val kClass = person::class // 객체의 클래스 정보 가져오기

    println("클래스 이름: ${kClass.simpleName}") // 클래스 이름 출력
    // "클래스 이름: Person"이 출력됩니다.

    // 클래스의 속성 정보 가져오기
    kClass.memberProperties.forEach { property ->
        println("속성 이름: ${property.name}, 값: ${property.get(person)}")
        // 속성 이름과 값을 출력합니다.
    }
}

실행 결과

클래스 이름: Person
속성 이름: name, 값: Alice
속성 이름: age, 값: 30

코드 한 줄씩 동작 설명

  1. data class Person(val name: String, val age: Int) - Person이라는 데이터를 표현하는 클래스를 정의합니다.
  2. val person = Person("Alice", 30) - Person 객체를 생성하며, 이름과 나이를 초기화합니다.
  3. val kClass = person::class - 생성된 person 객체의 클래스 정보를 가져옵니다.
  4. println("클래스 이름: ${kClass.simpleName}") - 클래스의 이름을 출력합니다.
  5. kClass.memberProperties.forEach { property -> ... } - 클래스의 모든 속성을 반복하며 정보를 출력합니다.
  6. 4. 실전 활용 예제

    예제 1: 동적 속성 변경

    쇼핑몰에서 사용자 정보를 관리하는 상황을 가정해 봅시다. 사용자의 정보를 동적으로 변경해야 하는 경우에 Reflection을 활용할 수 있습니다.

    data class User(var username: String, var email: String)
    
    fun updateUserProperty(user: User, propertyName: String, newValue: Any) {
        val kClass = user::class
        val property = kClass.members.find { it.name == propertyName } as? kotlin.reflect.KMutableProperty1<User, Any>
        property?.set(user, newValue) // 속성 값 변경
    }
    
    fun main() {
        val user = User("john_doe", "[email protected]")
        updateUserProperty(user, "email", "[email protected]") // 이메일 변경
        println(user) // User(username=john_doe, [email protected])
    }

    예제 2: 메소드 동적 호출

    어떤 상황에서는 특정 조건에 따라 메소드를 동적으로 호출해야 할 수도 있습니다.

    class Calculator {
        fun add(a: Int, b: Int): Int = a + b
        fun subtract(a: Int, b: Int): Int = a - b
    }
    
    fun invokeMethod(calculator: Calculator, methodName: String, vararg args: Any?): Any? {
        val method = calculator::class.members.find { it.name == methodName } as? kotlin.reflect.KFunction<>
        return method?.call(calculator, args)
    }
    
    fun main() {
        val calculator = Calculator()
        val result = invokeMethod(calculator, "add", 5, 3) // add 메소드 호출
        println(result) // 8 출력
    }

    5. 흔한 실수와 주의사항

    실수 1: 잘못된 속성 이름 사용

    // 잘못된 코드
    updateUserProperty(user, "user_email", "[email protected]") // 잘못된 속성 이름
    
    // 올바른 코드
    updateUserProperty(user, "email", "[email protected]") // 올바른 속성 이름
    • 주의: 속성 이름은 정확히 맞아야 합니다. 오타가 나면 NullPointerException이 발생할 수 있습니다.
    • 실수 2: Immutable Property 수정

      data class Person(val name: String) // immutable 속성
      
      // 잘못된 코드
      fun updateName(person: Person, newName: String) {
          person::class.memberProperties.find { it.name == "name" }?.set(person, newName) // 오류 발생
      }
    • 주의: immutable 속성은 수정할 수 없습니다. 변경 가능한 속성에서만 사용하십시오.
    • 6. 정리

    • Reflection은 객체의 메타데이터를 런타임에 탐색하고 조작할 수 있는 기능입니다.
    • 클래스, 속성, 메소드에 대한 동적 접근을 가능하게 합니다.
    • 실무에서 유용하게 활용될 수 있는 다양한 패턴이 있습니다.
    • 다음에는 Kotlin의 고급 기능인 AOP(Aspect-Oriented Programming)이나 DSL(Domain Specific Language) 설계에 대해 학습하는 것을 추천합니다.